The Application_BeginRequest() handler is the first step in the Asp.Net life cycle. Look here:
https://docs.microsoft.com/en-us/iis/application-frameworks/building-and-running-aspnet-applications/aspnet-integration-with-iis
When a handler is executing (which is your page), it has its own life cycle:
https://docs.microsoft.com/en-us/previous-versions/ms178472(v=vs.140)?redirectedfrom=MSDN
And this documentation says:
Start
In the start stage, page properties such as Request and Response are
set. At this stage, the page also determines whether the request is a
postback or a new request and sets the IsPostBack property. The page
also sets the UICulture property.
When the available events are checked, we see:
PreInit
Raised after the start stage is complete and before the initialization
stage begins.
Therefore; it seems that the earliest stage you can change the UICulture is the PreInit stage. The most appropriate place however, is the InitializeCulture method which serves this specific purpose:
public partial class _Default : Page
{
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
HttpCookie languageCookie = Request.Cookies["lang"];
if (languageCookie != null)
{
if (languageCookie.Value == "en")
{
base.Culture = base.UICulture = CultureInfo.GetCultureInfo("en-US").Name;
}
}
}
protected override void InitializeCulture()
{
// Or do it here. This is more appropriate.
}
...
...
}
EDIT:
Despite being shared accross multiple pages, the culture information should not be set in the Master Page's event handlers, because as can be seen in the following trace output, when a page uses a master page, the master page is interpreted as a control of the page and the Page_Load event of this master page is executed during LoadControls() which is executed after the Page's Page_Load handler.
I also want to mention the tracing feature here. By enabling tracing, it is possible to see a lot of information about the page's execution process, its children, all the timings, headers etc.:
In the web.config file, under <system.web>:
<trace pageOutput="true" requestLimit="10" enabled="true" localOnly="true" traceMode="SortByTime" mostRecent="true"/>
Or read here for the <system.webServer> equivalent:
https://docs.microsoft.com/en-us/iis/configuration/system.webserver/tracing/
Control Tree
Control UniqueID Type Render Size Bytes (including children) ViewState Size Bytes (excluding children) ControlState Size Bytes (excluding children)
__Page ASP.default_aspx 1104 0 0
ctl00 ASP.masterpage_master 1104 0 0
ctl00$ctl02 System.Web.UI.LiteralControl 68 0 0
ctl00$ctl00 System.Web.UI.HtmlControls.HtmlHead 48 0 0
ctl00$ctl01 System.Web.UI.HtmlControls.HtmlTitle 29 0 0
ctl00$head System.Web.UI.WebControls.ContentPlaceHolder 6 0 0
ctl00$head$ctl00 System.Web.UI.LiteralControl 6 0 0
ctl00$ctl03 System.Web.UI.LiteralControl 14 0 0
form1 System.Web.UI.HtmlControls.HtmlForm 954 0 0
ctl00$ctl04 System.Web.UI.LiteralControl 21 0 0
ctl00$ContentPlaceHolder1 System.Web.UI.WebControls.ContentPlaceHolder 291 0 0
ctl00$ContentPlaceHolder1$ctl00 System.Web.UI.LiteralControl 198 0 0
ctl00$ContentPlaceHolder1$hdn1 System.Web.UI.WebControls.HiddenField 91 0 0
ctl00$ContentPlaceHolder1$ctl01 System.Web.UI.LiteralControl 2 0 0
ctl00$ctl05 System.Web.UI.LiteralControl 18 0 0
ctl00$ctl06 System.Web.UI.LiteralControl 20 0 0