void ControladorInternacionalizacion::AddCatalog(const std::string& catalogName)
{
        wxString strTmp = FROMPATH(catalogName);
        wxLocale *pLoc = wxGetLocale();
        if (pLoc != NULL) {
                pLoc->AddCatalog(strTmp);
        }
}
ControladorInternacionalizacion::~ControladorInternacionalizacion()
{
        wxLocale *pLoc = wxGetLocale();
        if(pLoc != NULL) {
                pLoc->DestroyLanguagesDB();
                delete pLoc;
        }
}
示例#3
0
void CFileZillaApp::InitLocale()
{
	wxString language = COptions::Get()->GetOption(OPTION_LANGUAGE);
	const wxLanguageInfo* pInfo = wxLocale::FindLanguageInfo(language);
	if (!language.empty()) {
#ifdef __WXGTK__
		if (CInitializer::error) {
			wxString error;

			wxLocale *loc = wxGetLocale();
			const wxLanguageInfo* currentInfo = loc ? loc->GetLanguageInfo(loc->GetLanguage()) : 0;
			if (!loc || !currentInfo) {
				if (!pInfo)
					error.Printf(_("Failed to set language to %s, using default system language."),
						language);
				else
					error.Printf(_("Failed to set language to %s (%s), using default system language."),
						pInfo->Description, language);
			}
			else {
				wxString currentName = currentInfo->CanonicalName;

				if (!pInfo)
					error.Printf(_("Failed to set language to %s, using default system language (%s, %s)."),
						language, loc->GetLocale(),
						currentName);
				else
					error.Printf(_("Failed to set language to %s (%s), using default system language (%s, %s)."),
						pInfo->Description, language, loc->GetLocale(),
						currentName);
			}

			error += _T("\n");
			error += _("Please make sure the requested locale is installed on your system.");
			wxMessageBoxEx(error, _("Failed to change language"), wxICON_EXCLAMATION);

			COptions::Get()->SetOption(OPTION_LANGUAGE, _T(""));
		}
#else
		if (!pInfo || !SetLocale(pInfo->Language)) {
			for( language = GetFallbackLocale(language); !language.empty(); language = GetFallbackLocale(language) ) {
				const wxLanguageInfo* fallbackInfo = wxLocale::FindLanguageInfo(language);
				if( fallbackInfo && SetLocale(fallbackInfo->Language )) {
					COptions::Get()->SetOption(OPTION_LANGUAGE, language.ToStdWstring());
					return;
				}
			}
			COptions::Get()->SetOption(OPTION_LANGUAGE, std::wstring());
			if (pInfo && !pInfo->Description.empty())
				wxMessageBoxEx(wxString::Format(_("Failed to set language to %s (%s), using default system language"), pInfo->Description, language), _("Failed to change language"), wxICON_EXCLAMATION);
			else
				wxMessageBoxEx(wxString::Format(_("Failed to set language to %s, using default system language"), language), _("Failed to change language"), wxICON_EXCLAMATION);
		}
#endif
	}
}
ControladorInternacionalizacion::ControladorInternacionalizacion()
{
        m_idiomaInterfazSesion = GetIdiomaInterfaz();
        //se inicializa el soporte de idioma, leyendolo de la configuracion...
        wxLocale *pLoc = wxGetLocale();
        wxString pathLang = FROMPATH(GNC::Entorno::Instance()->GetGinkgoLanguageDir());
        if (pLoc == NULL) {
                pLoc = new wxLocale();
        }
        pLoc->AddCatalogLookupPathPrefix(pathLang);
        pLoc->Init(m_idiomaInterfazSesion);
        setlocale(LC_NUMERIC, "C");
}
示例#5
0
wxLayoutDirection wxAppBase::GetLayoutDirection() const
{
#if wxUSE_INTL
    const wxLocale *const locale = wxGetLocale();
    if ( locale )
    {
        const wxLanguageInfo *const
            info = wxLocale::GetLanguageInfo(locale->GetLanguage());

        if ( info )
            return info->LayoutDirection;
    }
#endif // wxUSE_INTL

    // we don't know
    return wxLayout_Default;
}
示例#6
0
文件: helpext.cpp 项目: EdgarTx/wx
// file is a misnomer as it's the name of the base help directory
bool wxExtHelpController::LoadFile(const wxString& file)
{
    wxFileName helpDir(wxFileName::DirName(file));
    helpDir.MakeAbsolute();

    bool dirExists = false;

#if wxUSE_INTL
    // If a locale is set, look in file/localename, i.e. If passed
    // "/usr/local/myapp/help" and the current wxLocale is set to be "de", then
    // look in "/usr/local/myapp/help/de/" first and fall back to
    // "/usr/local/myapp/help" if that doesn't exist.
    const wxLocale * const loc = wxGetLocale();
    if ( loc )
    {
        wxString locName = loc->GetName();

        // the locale is in general of the form xx_YY.zzzz, try the full firm
        // first and then also more general ones
        wxFileName helpDirLoc(helpDir);
        helpDirLoc.AppendDir(locName);
        dirExists = helpDirLoc.DirExists();

        if ( ! dirExists )
        {
            // try without encoding
            const wxString locNameWithoutEncoding = locName.BeforeLast(_T('.'));
            if ( !locNameWithoutEncoding.empty() )
            {
                helpDirLoc = helpDir;
                helpDirLoc.AppendDir(locNameWithoutEncoding);
                dirExists = helpDirLoc.DirExists();
            }
        }

        if ( !dirExists )
        {
            // try without country part
            wxString locNameWithoutCountry = locName.BeforeLast(_T('_'));
            if ( !locNameWithoutCountry.empty() )
            {
                helpDirLoc = helpDir;
                helpDirLoc.AppendDir(locNameWithoutCountry);
                dirExists = helpDirLoc.DirExists();
            }
        }

        if ( dirExists )
            helpDir = helpDirLoc;
    }
#endif // wxUSE_INTL

    if ( ! dirExists && !helpDir.DirExists() )
    {
        wxLogError(_("Help directory \"%s\" not found."),
                   helpDir.GetFullPath().c_str());
        return false;
    }

    const wxFileName mapFile(helpDir.GetFullPath(), WXEXTHELP_MAPFILE);
    if ( ! mapFile.FileExists() )
    {
        wxLogError(_("Help file \"%s\" not found."),
                   mapFile.GetFullPath().c_str());
        return false;
    }

    DeleteList();
    m_MapList = new wxList;
    m_NumOfEntries = 0;

    wxTextFile input;
    if ( !input.Open(mapFile.GetFullPath()) )
        return false;

    for ( wxString& line = input.GetFirstLine();
          !input.Eof();
          line = input.GetNextLine() )
    {
        if ( !ParseMapFileLine(line) )
        {
            wxLogWarning(_("Line %lu of map file \"%s\" has invalid syntax, skipped."),
                         (unsigned long)input.GetCurrentLine(),
                         mapFile.GetFullPath().c_str());
        }
    }

    if ( !m_NumOfEntries )
    {
        wxLogError(_("No valid mappings found in the file \"%s\"."),
                   mapFile.GetFullPath().c_str());
        return false;
    }

    m_helpDir = helpDir.GetFullPath(); // now it's valid
    return true;
}
示例#7
0
文件: i18n.cpp 项目: tsiru/pcsx2
// This method sets the requested language, based on wxLanguage id and an optional 'confirmation'
// canonical code.  If the canonical code is provided, it is used to confirm that the ID matches
// the intended language/dialect.  If the ID and canonical do not match, this method will use
// wx's FindLAnguageInfo to provide a "best guess" canonical match (usually relying on the user's
// operating system default).
//
// Rationale: wxWidgets language IDs are just simple enums, and not especially unique.  Future
// versions of PCSX2 may have language ID changes if built against new/different versions of wx.
// To prevent PCSX2 from selecting a completely wrong language when upgraded, we double-check
// the wxLanguage code against the canonical name.  We can't simply use canonical names either
// because those are not unique (dialects of chinese, for example), and wx returns the generic
// form over a specific dialect, when given a choice.  Thus a two-tier check is required.
//
//  wxLanguage for specific dialect, and canonical as a fallback/safeguard in case the wxLanguage
//  id appears to be out of date.
//
//
bool i18n_SetLanguage( wxLanguage wxLangId, const wxString& langCode )
{
	const wxLanguageInfo* info = wxLocale::GetLanguageInfo(wxLangId);

	// Check if you can load a similar language in case the current one is not yet provided
	if (info) {
		wxLanguage LangId_fallback = i18n_FallbackToAnotherLang((wxLanguage)info->Language);
		if (LangId_fallback != (wxLanguage)info->Language)
			info = wxLocale::GetLanguageInfo(LangId_fallback);
	}

	// note: language canonical name mismatch probably means wxWidgets version changed since 
	// the user's ini file was provided.  Missing/invalid ID probably means the same thing.
	// If either is true, and the caller provided a canonical name, then let wx do a best
	// match based on the canonical name.

	if (!info || (!langCode.IsEmpty() && (langCode.CmpNoCase(info->CanonicalName) != 0)))
	{
		if (!info)
			Console.Warning( "Invalid language identifier (wxID=%d)", wxLangId );

		if (!langCode.IsEmpty() && (langCode.CmpNoCase(L"default")!=0))
		{
			info = wxLocale::FindLanguageInfo(langCode);
			if (!info)
				Console.Warning( "Unrecognized language canonical name '%ls'", langCode.c_str() );
		}
	}

	if (!info) return false;
	if (wxGetLocale() && (info->Language == wxGetLocale()->GetLanguage())) return true;
	
	ScopedPtr<wxLocale> locale( new wxLocale(info->Language) );

	if( !locale->IsOk() )
	{
		Console.Warning( L"SetLanguage: '%s' [%s] is not supported by the operating system",
			i18n_GetBetterLanguageName(info).c_str(), locale->GetCanonicalName().c_str()
		);
		return false;
	}

	wxLangId = (wxLanguage)locale->GetLanguage();
	
	if (wxLangId == wxLANGUAGE_UNKNOWN)
	{
		Console.WriteLn("System-default language is unknown?  Defaulting back to English/US.");
		wxLangId = wxLANGUAGE_ENGLISH_US;
	}

	// English/US is built in, so no need to load MO/PO files.
	if( pxIsEnglish(wxLangId) )
	{
		locale.DetachPtr();
		return true;
	}
	
	Console.WriteLn( L"Loading language translation databases for '%s' [%s]",
		i18n_GetBetterLanguageName(info).c_str(), locale->GetCanonicalName().c_str()
	);

	static const wxChar* dictFiles[] =
	{
		L"pcsx2_Main",
		L"pcsx2_Iconized"
	};
	
	bool foundone = false;
	for (uint i=0; i<ArraySize(dictFiles); ++i)
	{
		if (!dictFiles[i]) continue;

		if (!locale->AddCatalog(dictFiles[i]))
			Console.Indent().WriteLn(Color_StrongYellow, "%ls not found -- translation dictionary may be incomplete.", dictFiles[i]);
		else
			foundone = true;
	}

	if (!foundone)	
	{
		Console.Warning("SetLanguage: Requested translation is not implemented yet.");
		return false;
	}

	locale.DetachPtr();
	return true;
}
示例#8
0
/* static */
wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
{
    CFLocaleRef userLocaleRefRaw;
    if ( wxGetLocale() )
    {
        userLocaleRefRaw = CFLocaleCreate
                        (
                                kCFAllocatorDefault,
                                wxCFStringRef(wxGetLocale()->GetCanonicalName())
                        );
    }
    else // no current locale, use the default one
    {
        userLocaleRefRaw = CFLocaleCopyCurrent();
    }

    wxCFRef<CFLocaleRef> userLocaleRef(userLocaleRefRaw);

    CFStringRef cfstr = 0;
    switch ( index )
    {
        case wxLOCALE_THOUSANDS_SEP:
            cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleGroupingSeparator);
            break;

        case wxLOCALE_DECIMAL_POINT:
            cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleDecimalSeparator);
            break;

        case wxLOCALE_SHORT_DATE_FMT:
        case wxLOCALE_LONG_DATE_FMT:
        case wxLOCALE_DATE_TIME_FMT:
        case wxLOCALE_TIME_FMT:
            {
                CFDateFormatterStyle dateStyle = kCFDateFormatterNoStyle;
                CFDateFormatterStyle timeStyle = kCFDateFormatterNoStyle;
                switch (index )
                {
                    case wxLOCALE_SHORT_DATE_FMT:
                        dateStyle = kCFDateFormatterShortStyle;
                        break;
                    case wxLOCALE_LONG_DATE_FMT:
                        dateStyle = kCFDateFormatterFullStyle;
                        break;
                    case wxLOCALE_DATE_TIME_FMT:
                        dateStyle = kCFDateFormatterFullStyle;
                        timeStyle = kCFDateFormatterMediumStyle;
                        break;
                    case wxLOCALE_TIME_FMT:
                        timeStyle = kCFDateFormatterMediumStyle;
                        break;
                    default:
                        wxFAIL_MSG( "unexpected time locale" );
                        return wxString();
                }
                wxCFRef<CFDateFormatterRef> dateFormatter( CFDateFormatterCreate
                    (NULL, userLocaleRef, dateStyle, timeStyle));
                wxCFStringRef cfs = wxCFRetain( CFDateFormatterGetFormat(dateFormatter ));
                wxString format = TranslateFromUnicodeFormat(cfs.AsString());
                // we always want full years
                format.Replace("%y","%Y");
                return format;
            }
            break;

        default:
            wxFAIL_MSG( "Unknown locale info" );
            return wxString();
    }

    wxCFStringRef str(wxCFRetain(cfstr));
    return str.AsString();
}
示例#9
0
/* static */
wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat)
{
    wxUint32 lcid = LOCALE_USER_DEFAULT;
    if ( wxGetLocale() )
    {
        const wxLanguageInfo * const
            info = GetLanguageInfo(wxGetLocale()->GetLanguage());
        if ( info )
            lcid = info->GetLCID();
    }

    wxString str;

    wxChar buf[256];
    buf[0] = wxT('\0');

    switch ( index )
    {
        case wxLOCALE_THOUSANDS_SEP:
            if ( ::GetLocaleInfo(lcid, LOCALE_STHOUSAND, buf, WXSIZEOF(buf)) )
                str = buf;
            break;

        case wxLOCALE_DECIMAL_POINT:
            if ( ::GetLocaleInfo(lcid,
                                 cat == wxLOCALE_CAT_MONEY
                                     ? LOCALE_SMONDECIMALSEP
                                     : LOCALE_SDECIMAL,
                                 buf,
                                 WXSIZEOF(buf)) )
                str = buf;
            break;

        case wxLOCALE_SHORT_DATE_FMT:
        case wxLOCALE_LONG_DATE_FMT:
        case wxLOCALE_TIME_FMT:
            if ( ::GetLocaleInfo(lcid, GetLCTYPEFormatFromLocalInfo(index),
                                 buf, WXSIZEOF(buf)) )
            {
                return TranslateFromUnicodeFormat(buf);
            }
            break;

        case wxLOCALE_DATE_TIME_FMT:
            // there doesn't seem to be any specific setting for this, so just
            // combine date and time ones
            //
            // we use the short date because this is what "%c" uses by default
            // ("%#c" uses long date but we have no way to specify the
            // alternate representation here)
            {
                const wxString datefmt = GetInfo(wxLOCALE_SHORT_DATE_FMT);
                if ( datefmt.empty() )
                    break;

                const wxString timefmt = GetInfo(wxLOCALE_TIME_FMT);
                if ( timefmt.empty() )
                    break;

                str << datefmt << ' ' << timefmt;
            }
            break;

        default:
            wxFAIL_MSG( "unknown wxLocaleInfo" );
    }

    return str;
}
示例#10
0
int wxMessageDialog::ShowModal()
{
    if ( !wxTheApp->GetTopWindow() )
    {
        // when the message box is shown from wxApp::OnInit() (i.e. before the
        // message loop is entered), this must be done or the next message box
        // will never be shown - just try putting 2 calls to wxMessageBox() in
        // OnInit() to see it
        while ( wxTheApp->Pending() )
            wxTheApp->Dispatch();
    }

    // use the top level window as parent if none specified
    m_parent = GetParentForModalDialog();
    HWND hWnd = m_parent ? GetHwndOf(m_parent) : NULL;

#if wxUSE_INTL
    // native message box always uses the current user locale but the program
    // may be using a different one and in this case we need to manually
    // translate the button labels to avoid mismatch between the language of
    // the message box text and its buttons
    wxLocale * const loc = wxGetLocale();
    if ( loc && loc->GetLanguage() != wxLocale::GetSystemLanguage() )
    {
        if ( m_dialogStyle & wxYES_NO )
        {
            // use the strings with mnemonics here as the native message box
            // does
            SetYesNoLabels(_("&Yes"), _("&No"));
        }

        // we may or not have the Ok/Cancel buttons but either we do have them
        // or we already made the labels custom because we called
        // SetYesNoLabels() above so doing this does no harm -- and is
        // necessary in wxYES_NO | wxCANCEL case
        //
        // note that we don't use mnemonics here for consistency with the
        // native message box (which probably doesn't use them because
        // Enter/Esc keys can be already used to dismiss the message box
        // using keyboard)
        SetOKCancelLabels(_("OK"), _("Cancel"));
    }
#endif // wxUSE_INTL

    // translate wx style in MSW
    unsigned int msStyle;
    const long wxStyle = GetMessageDialogStyle();
    if ( wxStyle & wxYES_NO )
    {
#if !(defined(__SMARTPHONE__) && defined(__WXWINCE__))
        if (wxStyle & wxCANCEL)
            msStyle = MB_YESNOCANCEL;
        else
#endif // !(__SMARTPHONE__ && __WXWINCE__)
            msStyle = MB_YESNO;

        if ( wxStyle & wxNO_DEFAULT )
            msStyle |= MB_DEFBUTTON2;
        else if ( wxStyle & wxCANCEL_DEFAULT )
            msStyle |= MB_DEFBUTTON3;
    }
    else // without Yes/No we're going to have an OK button
    {
        if ( wxStyle & wxCANCEL )
        {
            msStyle = MB_OKCANCEL;

            if ( wxStyle & wxCANCEL_DEFAULT )
                msStyle |= MB_DEFBUTTON2;
        }
        else // just "OK"
        {
            msStyle = MB_OK;
        }
    }

    // set the icon style
    switch ( GetEffectiveIcon() )
    {
        case wxICON_ERROR:
            msStyle |= MB_ICONHAND;
            break;

        case wxICON_WARNING:
            msStyle |= MB_ICONEXCLAMATION;
            break;

        case wxICON_QUESTION:
            msStyle |= MB_ICONQUESTION;
            break;

        case wxICON_INFORMATION:
            msStyle |= MB_ICONINFORMATION;
            break;
    }

    if ( wxStyle & wxSTAY_ON_TOP )
        msStyle |= MB_TOPMOST;

#ifndef __WXWINCE__
    if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
        msStyle |= MB_RTLREADING | MB_RIGHT;
#endif

    if (hWnd)
        msStyle |= MB_APPLMODAL;
    else
        msStyle |= MB_TASKMODAL;

    // per MSDN documentation for MessageBox() we can prefix the message with 2
    // right-to-left mark characters to tell the function to use RTL layout
    // (unfortunately this only works in Unicode builds)
    wxString message = GetFullMessage();
#if wxUSE_UNICODE
    if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
    {
        // NB: not all compilers support \u escapes
        static const wchar_t wchRLM = 0x200f;
        message.Prepend(wxString(wchRLM, 2));
    }
#endif // wxUSE_UNICODE

#if wxUSE_MSGBOX_HOOK
    // install the hook in any case as we don't know in advance if the message
    // box is not going to be too big (requiring the replacement of the static
    // control with an edit one)
    const DWORD tid = ::GetCurrentThreadId();
    m_hook = ::SetWindowsHookEx(WH_CBT,
                                &wxMessageDialog::HookFunction, NULL, tid);
    HookMap()[tid] = this;
#endif // wxUSE_MSGBOX_HOOK

    // do show the dialog
    int msAns = MessageBox(hWnd, message.wx_str(), m_caption.wx_str(), msStyle);
    int ans;
    switch (msAns)
    {
        default:
            wxFAIL_MSG(wxT("unexpected ::MessageBox() return code"));
            // fall through

        case IDCANCEL:
            ans = wxID_CANCEL;
            break;
        case IDOK:
            ans = wxID_OK;
            break;
        case IDYES:
            ans = wxID_YES;
            break;
        case IDNO:
            ans = wxID_NO;
            break;
    }
    return ans;
}
示例#11
0
// Read a XDG *.desktop file of type 'Application'
void wxMimeTypesManagerImpl::LoadXDGApp(const wxString& filename)
{
    wxLogTrace(TRACE_MIME, wxT("loading XDG file %s"), filename.c_str());

    wxMimeTextFile file(filename);
    if ( !file.Open() )
        return;

    // Here, only type 'Application' should be considered.
    int nIndex = file.pIndexOf( "Type=" );
    if (nIndex != wxNOT_FOUND && file.GetCmd(nIndex) != "application")
        return;

    // The hidden entry specifies a file to be ignored.
    nIndex = file.pIndexOf( "Hidden=" );
    if (nIndex != wxNOT_FOUND && file.GetCmd(nIndex) == "true")
        return;

    // Semicolon separated list of mime types handled by the application.
    nIndex = file.pIndexOf( wxT("MimeType=") );
    if (nIndex == wxNOT_FOUND)
        return;
    wxString mimetypes = file.GetCmd (nIndex);

    // Name of the application
    wxString nameapp;
    nIndex = wxNOT_FOUND;
#if wxUSE_INTL // try "Name[locale name]" first
    wxLocale *locale = wxGetLocale();
    if ( locale )
        nIndex = file.pIndexOf(wxT("Name[")+locale->GetName()+wxT("]="));
#endif // wxUSE_INTL
    if(nIndex == wxNOT_FOUND)
        nIndex = file.pIndexOf( wxT("Name=") );
    if(nIndex != wxNOT_FOUND)
        nameapp = file.GetCmd(nIndex);

    // Icon of the application.
    wxString nameicon, namemini;
    nIndex = wxNOT_FOUND;
#if wxUSE_INTL // try "Icon[locale name]" first
    if ( locale )
        nIndex = file.pIndexOf(wxT("Icon[")+locale->GetName()+wxT("]="));
#endif // wxUSE_INTL
    if(nIndex == wxNOT_FOUND)
        nIndex = file.pIndexOf( wxT("Icon=") );
    if(nIndex != wxNOT_FOUND) {
        nameicon = wxString(wxT("--icon ")) + file.GetCmd(nIndex);
        namemini = wxString(wxT("--miniicon ")) + file.GetCmd(nIndex);
    }

    // Replace some of the field code in the 'Exec' entry.
    // TODO: deal with %d, %D, %n, %N, %k and %v (but last one is deprecated)
    nIndex = file.pIndexOf( wxT("Exec=") );
    if (nIndex == wxNOT_FOUND)
        return;
    wxString sCmd = file.GetCmd(nIndex);
    // we expect %f; others including  %F and %U and %u are possible
    sCmd.Replace(wxT("%F"), wxT("%f"));
    sCmd.Replace(wxT("%U"), wxT("%f"));
    sCmd.Replace(wxT("%u"), wxT("%f"));
    if (0 == sCmd.Replace ( wxT("%f"), wxT("%s") ))
        sCmd = sCmd + wxT(" %s");
    sCmd.Replace(wxT("%c"), nameapp);
    sCmd.Replace(wxT("%i"), nameicon);
    sCmd.Replace(wxT("%m"), namemini);

    wxStringTokenizer tokenizer(mimetypes, wxT(";"));
    while(tokenizer.HasMoreTokens()) {
        wxString mimetype = tokenizer.GetNextToken().Lower();
        nIndex = m_aTypes.Index(mimetype);
        if(nIndex != wxNOT_FOUND) { // is this a known MIME type?
            wxMimeTypeCommands* entry = m_aEntries[nIndex];
            entry->AddOrReplaceVerb(wxT("open"), sCmd);
        }
    }
}
bool CWelcomeDialog::Run(wxWindow* parent, bool force /*=false*/, bool delay /*=false*/)
{
	const wxString ownVersion = CBuildInfo::GetVersion();
	wxString greetingVersion = COptions::Get()->GetOption(OPTION_GREETINGVERSION);

	wxString const resources = COptions::Get()->GetOption(OPTION_GREETINGRESOURCES);
	COptions::Get()->SetOption(OPTION_GREETINGRESOURCES, _T(""));

	if (!force) {
		if (COptions::Get()->GetOptionVal(OPTION_DEFAULT_KIOSKMODE) == 2) {
			if (delay)
				delete this;
			return true;
		}

		if (!greetingVersion.empty() &&
			CBuildInfo::ConvertToVersionNumber(ownVersion.c_str()) <= CBuildInfo::ConvertToVersionNumber(greetingVersion.c_str()))
		{
			// Been there done that
			if (delay)
				delete this;
			return true;
		}
		COptions::Get()->SetOption(OPTION_GREETINGVERSION, ownVersion.ToStdWstring());

		if (greetingVersion.empty() && !COptions::Get()->GetOptionVal(OPTION_DEFAULT_KIOSKMODE))
			COptions::Get()->SetOption(OPTION_PROMPTPASSWORDSAVE, 1);
	}

	if (!Load(parent, _T("ID_WELCOME"))) {
		if (delay) {
			delete this;
		}
		return false;
	}

	InitFooter(force ? wxString() : resources);

	xrc_call(*this, "ID_FZVERSION", &wxStaticText::SetLabel, _T("FileZilla ") + CBuildInfo::GetVersion());

	wxString const url = _T("https://welcome.filezilla-project.org/welcome?type=client&category=%s&version=") + ownVersion;

	if (!greetingVersion.empty()) {
		xrc_call(*this, "ID_LINK_NEWS", &wxHyperlinkCtrl::SetURL, wxString::Format(url, _T("news")) + _T("&oldversion=") + greetingVersion);
		xrc_call(*this, "ID_LINK_NEWS", &wxHyperlinkCtrl::SetLabel, wxString::Format(_("New features and improvements in %s"), CBuildInfo::GetVersion()));
	}
	else {
		xrc_call(*this, "ID_LINK_NEWS", &wxHyperlinkCtrl::Hide);
		xrc_call(*this, "ID_HEADING_NEWS", &wxStaticText::Hide);
	}

	xrc_call(*this, "ID_DOCUMENTATION_BASIC", &wxHyperlinkCtrl::SetURL, wxString::Format(url, _T("documentation_basic")));
	xrc_call(*this, "ID_DOCUMENTATION_NETWORK", &wxHyperlinkCtrl::SetURL, wxString::Format(url, _T("documentation_network")));
	xrc_call(*this, "ID_DOCUMENTATION_MORE", &wxHyperlinkCtrl::SetURL, wxString::Format(url, _T("documentation_more")));
	xrc_call(*this, "ID_SUPPORT_FORUM", &wxHyperlinkCtrl::SetURL, wxString::Format(url, _T("support_forum")));
	xrc_call(*this, "ID_SUPPORT_MORE", &wxHyperlinkCtrl::SetURL, wxString::Format(url, _T("support_more")));

#ifdef FZ_WINDOWS
	// Add phone support link in official Windows builds builds...
	if (CBuildInfo::GetBuildType() == _T("official")) {
		auto lang = wxGetLocale() ? wxGetLocale()->GetName() : wxString();
		// but only in English...
		if (lang.StartsWith(_T("en"))) {
			auto const now = fz::datetime::now();
			// while the build is fresh...
			if ((now - CBuildInfo::GetBuildDate()).get_days() < 60) {
				// and only for US and Canada, so limit by timezone
				auto ref = fz::datetime(now.format("%Y%m%d%H%M%S", fz::datetime::utc), fz::datetime::utc);
				auto offset = fz::datetime(ref.format("%Y%m%d%H%M%S", fz::datetime::utc), fz::datetime::local);
				auto diff = (ref - offset).get_hours();
				if (diff >= -9 && diff <= -3) {
					auto sizer = xrc_call(*this, "ID_SUPPORT_MORE", &wxWindow::GetContainingSizer);
					if (sizer) {
						auto link = new wxHyperlinkCtrl(sizer->GetContainingWindow(), wxID_ANY, _T("Phone support"), _T("https://filezilla-project.org/phone_support.php"));
						sizer->Insert(0, link);
					}
				}
			}
		}
	}
#endif

	Layout();

	GetSizer()->Fit(this);

	if (delay) {
		m_delayedShowTimer.SetOwner(this);
		m_delayedShowTimer.Start(10, true);
	}
	else
		ShowModal();

	return true;
}