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; } }
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"); }
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; }
// 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; }
// 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; }
/* 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(); }
/* 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; }
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; }
// 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; }