about localization and satellite assemblies

T

Tony Johansson

This is a small code snippet from a working program where I have two
satellite assemblies for the German langauge and the french language. When
the passed culture is empty I have the english langauge.

So now to my question at what point in this code does the framework look up
the satellite assembly dll.?

public partial class BookOfTheDayForm : Form
{
public BookOfTheDayForm(string culture)
{
if (culture != string.Empty)
{
CultureInfo ci = new CultureInfo(culture);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
}

WelcomeMessage();
InitializeComponent();
SetDateAndNumber();
}
....
}

//Tony
 
T

Tony Johansson

Peter Duniho said:
In the code you posted, there is no access to any resource shown
whatsoever. So there's no need to look up the satellite assembly DLL at
all.

I suppose it's possible one of the methods called in the code you posted
might need a resource, but since you didn't post the code for any of those
methods, it's not possible to say which, if any, requires the localized
satellite assembly.

Pete

Here is the complete code that works fine. I just wonder if the satellite
assembly is loaded as soon as the app is started ?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Threading;

namespace Wrox.ProCSharp.Localization
{
public partial class BookOfTheDayForm : Form
{
public BookOfTheDayForm(string culture)
{
if (culture != string.Empty)
{
CultureInfo ci = new CultureInfo(culture);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
}
WelcomeMessage();
InitializeComponent();
SetDateAndNumber();
}

public void WelcomeMessage()
{
DateTime now = DateTime.Now;
string message = string.Empty; ;
if (now.Hour <= 12)
{
message = Properties.Resources.Good_Morning;
}
else if (now.Hour <= 19)
{
message = Properties.Resources.Good_Afternoon;
}
else
{
message = Properties.Resources.Good_Evening;
}
MessageBox.Show(message + "\n" + Properties.Resources.Message1);
}

public void SetDateAndNumber()
{
DateTime today = DateTime.Today;
textDate.Text = today.ToString("D");
int itemsSold = 327444;
textItemsSold.Text = itemsSold.ToString("###,###,###");
}
}

static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

string culture = string.Empty;
if (args.Length == 1)
{
culture = args[0];
}
Application.Run(new BookOfTheDayForm(culture));
}
}

partial class BookOfTheDayForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be
disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows Form Designer generated code

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new
System.ComponentModel.ComponentResourceManager(typeof(BookOfTheDayForm));
this.pictureFlag = new System.Windows.Forms.PictureBox();
this.labelBookOfTheDay = new System.Windows.Forms.Label();
this.textDate = new System.Windows.Forms.TextBox();
this.labelItemsSold = new System.Windows.Forms.Label();
this.textTitle = new System.Windows.Forms.TextBox();
this.textItemsSold = new System.Windows.Forms.TextBox();
((System.ComponentModel.ISupportInitialize)(this.pictureFlag)).BeginInit();
this.SuspendLayout();
//
// pictureFlag
//
this.pictureFlag.AccessibleDescription = null;
this.pictureFlag.AccessibleName = null;
resources.ApplyResources(this.pictureFlag, "pictureFlag");
this.pictureFlag.BackgroundImage = null;
this.pictureFlag.Font = null;
this.pictureFlag.ImageLocation = null;
this.pictureFlag.Name = "pictureFlag";
this.pictureFlag.TabStop = false;
//
// labelBookOfTheDay
//
this.labelBookOfTheDay.AccessibleDescription = null;
this.labelBookOfTheDay.AccessibleName = null;
resources.ApplyResources(this.labelBookOfTheDay,
"labelBookOfTheDay");
this.labelBookOfTheDay.Font = null;
this.labelBookOfTheDay.Name = "labelBookOfTheDay";
//
// textDate
//
this.textDate.AccessibleDescription = null;
this.textDate.AccessibleName = null;
resources.ApplyResources(this.textDate, "textDate");
this.textDate.BackgroundImage = null;
this.textDate.Font = null;
this.textDate.Name = "textDate";
//
// labelItemsSold
//
this.labelItemsSold.AccessibleDescription = null;
this.labelItemsSold.AccessibleName = null;
resources.ApplyResources(this.labelItemsSold, "labelItemsSold");
this.labelItemsSold.Font = null;
this.labelItemsSold.Name = "labelItemsSold";
//
// textTitle
//
this.textTitle.AccessibleDescription = null;
this.textTitle.AccessibleName = null;
resources.ApplyResources(this.textTitle, "textTitle");
this.textTitle.BackgroundImage = null;
this.textTitle.Font = null;
this.textTitle.Name = "textTitle";
//
// textItemsSold
//
this.textItemsSold.AccessibleDescription = null;
this.textItemsSold.AccessibleName = null;
resources.ApplyResources(this.textItemsSold, "textItemsSold");
this.textItemsSold.BackgroundImage = null;
this.textItemsSold.Font = null;
this.textItemsSold.Name = "textItemsSold";
//
// BookOfTheDayForm
//
this.AccessibleDescription = null;
this.AccessibleName = null;
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackgroundImage = null;
this.Controls.Add(this.textItemsSold);
this.Controls.Add(this.textTitle);
this.Controls.Add(this.labelItemsSold);
this.Controls.Add(this.textDate);
this.Controls.Add(this.labelBookOfTheDay);
this.Controls.Add(this.pictureFlag);
this.Font = null;
this.Icon = null;
this.Name = "BookOfTheDayForm";
((System.ComponentModel.ISupportInitialize)(this.pictureFlag)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}

#endregion

private System.Windows.Forms.PictureBox pictureFlag;
private System.Windows.Forms.Label labelBookOfTheDay;
private System.Windows.Forms.TextBox textDate;
private System.Windows.Forms.Label labelItemsSold;
private System.Windows.Forms.TextBox textTitle;
private System.Windows.Forms.TextBox textItemsSold;
}
}

//Tony
 
A

Arne Vajhøj

Here is the complete code that works fine. I just wonder if the satellite
assembly is loaded as soon as the app is started ?

public static void Trace(object sender, AssemblyLoadEventArgs args)
{
Console.WriteLine("Loaded: " + args.LoadedAssembly.Location);
}
public static void Main(string[] args)
{
AppDomain.CurrentDomain.AssemblyLoad += new
AssemblyLoadEventHandler(Trace);
...
}

will display what assemblies get loaded after Main starts
executing (loaded in current AppDomain that is).

If an assembly is not displayed but is used, then it must be loaded
before Main starts.

Arne
 
K

kndg

Here is the complete code that works fine. I just wonder if the satellite
assembly is loaded as soon as the app is started ?

I would say the satellite assembly is loaded as soon as the form is
instantiate. You can always check the loaded assemblies from the
following code,

[Conditional("DEBUG")]
public static void PrintLoadedAssemblies()
{
Assembly[] asemblies = AppDomain.CurrentDomain.GetAssemblies();

Debug.WriteLine("Loaded assemblies:");

foreach (var assembly in asemblies)
{
Debug.WriteLine(assembly.FullName);
}
}

Make two calls, one is before your form is created (at program.cs, in
Main method before the Application.Run(..) line) and another at the very
first line on your form constructor. Check the differences.

Basically, when the form is loaded, it will check the CurrentUICulture
and if it find the matching assembly, it will show your form using the
resource defined in that assembly.
 
K

kndg

This is a small code snippet from a working program where I have two
satellite assemblies for the German langauge and the french language. When
the passed culture is empty I have the english langauge.

So now to my question at what point in this code does the framework look up
the satellite assembly dll.?

public partial class BookOfTheDayForm : Form
{
public BookOfTheDayForm(string culture)
{
if (culture != string.Empty)
{
CultureInfo ci = new CultureInfo(culture);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
}

WelcomeMessage();
InitializeComponent();
SetDateAndNumber();
}
....
}

//Tony

I would say your form constructor is very fragile. What happen if the
form is passed an invalid string/culture? You also set the
CurrentUICulture at the form level which can cause inconsistent language
if have many forms.

From my experience doing a localizable application, I would store the
culture in a config file and set the CurrentUICulture at the application
level (means at programs.cs before the form is instantiate).

If you like the user to change the language at will, you can have below
methods.

private void SetLanguage(string language)
{
if (String.IsNullOrWhiteSpace(language))
{
return;
}

CultureInfo cultureInfo;

try
{
cultureInfo = new CultureInfo(language);
}
catch (ArgumentException)
{
return;
}

Thread.CurrentThread.CurrentUICulture = cultureInfo;

LocalizeForm();
}

private void LocalizeForm()
{
var resources = new
ComponentResourceManager(typeof(BookOfTheDayForm));

foreach (Control control in Controls)
{
resources.ApplyResources(control, control.Name);
}
}

For example, you can have a menu of supported languages and when the
user click on the desired language, just call the SetLanguage() method.
 
T

Tony Johansson

Arne Vajhøj said:
Here is the complete code that works fine. I just wonder if the satellite
assembly is loaded as soon as the app is started ?

public static void Trace(object sender, AssemblyLoadEventArgs
args)
{
Console.WriteLine("Loaded: " + args.LoadedAssembly.Location);
}
public static void Main(string[] args)
{
AppDomain.CurrentDomain.AssemblyLoad += new
AssemblyLoadEventHandler(Trace);
...
}

will display what assemblies get loaded after Main starts
executing (loaded in current AppDomain that is).

If an assembly is not displayed but is used, then it must be loaded
before Main starts.

Arne

yes the satellite assembly is loaded before main starts.

//Tony
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top