Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Internationalization / June 2007

Tip: Looking for answers? Try searching our database.

Check languages available for application

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Michael Nesslinger - 08 Jun 2007 11:28 GMT
I have an application that for now supports just two languages. Later
there will be more languages available. I need a way to check at runtime
what languages are available.
One quite time-consuming way would be to get all cultures and test for
each one if it is available. That leads to the next problem. If this is
the only way how do i do this with minimal cost of time.

Every bit of help is appreciated.

Michael Neßlinger
Michael S. Kaplan [MSFT] - 09 Jun 2007 01:49 GMT
If you use the following code, modified to point to your own assembly, you
can get the list you want:

http://blogs.msdn.com/michkap/archive/2006/03/25/560838.aspx

Signature

MichKa [Microsoft]
NLS Collation/Locale/Keyboard Technical Lead
Globalization Infrastructure, Fonts, and Tools
Blog: http://blogs.msdn.com/michkap

This posting is provided "AS IS" with
no warranties, and confers no rights.

>I have an application that for now supports just two languages. Later there
>will be more languages available. I need a way to check at runtime what
[quoted text clipped - 6 lines]
>
> Michael Neßlinger
Mihai N. - 09 Jun 2007 07:21 GMT
> I have an application that for now supports just two languages. Later
> there will be more languages available. I need a way to check at runtime
> what languages are available.
> One quite time-consuming way would be to get all cultures and test for
> each one if it is available. That leads to the next problem. If this is
> the only way how do i do this with minimal cost of time.

MichKa's blog offers the same solution you thought about: enumerate all
the locales and try them.

You can also enumerate the subfolders of the application folder anc check for
satelite DLLs.
If the application is bla.exe, then you might find:
       de\bla.resources.dll
       de-DE\bla.resources.dll
       es\bla.resources.dll
       fr\bla.resources.dll
       fr-FR\bla.resources.dll

Although it might seem faster (you are just checking for 4-5 folders),
it is not necessarily so. Disk access might be slower than enumerating
all the locales.
But if you enumerate the locales, checking each of them might still need
disk access.

I would try both solutions and time them.

Signature

Mihai Nita [Microsoft MVP, Windows - SDK]
http://www.mihai-nita.net
------------------------------------------
Replace _year_ with _ to get the real email

Mihai N. - 09 Jun 2007 08:26 GMT
> I would try both solutions and time them.

Just tried both, scanning folders is way-way faster.

//========================
public void ScanAllLocales() {
   System.Collections.SortedList rez = new
   System.Collections.SortedList();

   Assembly assembly = Assembly.GetAssembly(GetType());
   foreach(CultureInfo ci in
   CultureInfo.GetCultures(CultureTypes.SpecificCultures |
   CultureTypes.NeutralCultures)) {
       try
       {
           Assembly satellite = assembly.GetSatelliteAssembly(ci);
           rez.Add(ci.Name, ci);
       }
       catch (FileNotFoundException)
       {
       }
   }
}
//========================
public void ScanFolders()
{
   System.Collections.SortedList rez = new
   System.Collections.SortedList();

   Assembly assembly = Assembly.GetAssembly(GetType());
   String dir = System.IO.Path.GetDirectoryName(assembly.Location);
   foreach (string dname in System.IO.Directory.GetDirectories(dir, "*"))
   {
       try
       {
           System.Globalization.CultureInfo ci = new
           CultureInfo(System.IO.Path.GetFileName(dname)); try
           {
               Assembly satellite = assembly.GetSatelliteAssembly(ci);
               rez.Add(ci.Name, ci);
           }
           catch (FileNotFoundException)
           {
           }
       }
       catch (ArgumentException)
       {
       }
   }
}
//========================

Signature

Mihai Nita [Microsoft MVP, Windows - SDK]
http://www.mihai-nita.net
------------------------------------------
Replace _year_ with _ to get the real email

Michael S. Kaplan [MSFT] - 09 Jun 2007 14:36 GMT
My worry here is that a program might include cultures that would not load
on the system in question due to the culture being undefined; this kept me
looking for ones that were not only available but also loadable. :-)

But your code sample works around that quite nicely by verifying the
loadability of the ones that are there....

Signature

MichKa [Microsoft]
NLS Collation/Locale/Keyboard Technical Lead
Globalization Infrastructure, Fonts, and Tools
Blog: http://blogs.msdn.com/michkap

This posting is provided "AS IS" with
no warranties, and confers no rights.

>> I have an application that for now supports just two languages. Later
>> there will be more languages available. I need a way to check at runtime
[quoted text clipped - 23 lines]
>
> I would try both solutions and time them.
Michael Nesslinger - 10 Jun 2007 15:53 GMT
Michael S. Kaplan [MSFT] schrieb:
> My worry here is that a program might include cultures that would not load
> on the system in question due to the culture being undefined; this kept me
> looking for ones that were not only available but also loadable. :-)
>
> But your code sample works around that quite nicely by verifying the
> loadability of the ones that are there....

Thanks a lot to both of you. This works great and is quite fast.

But now i have got a new little problem. I would like to use the Visual
Studio Designer to design my dialogs and maybe write 1 or 2 translations
myself.

The other translations will be written by someone else. This person gets
for example the English .resx file and translates it (using a tool) into
a French .resx file. If i import them into my project and recompile
everything is o.k. and i can access the French language.

But if i compile and link the .resx file myself into a DLL an put it in
the proper folder it cannot be accessed. Only the translations compiled
with the project are available. I think i must load this DLL before it
can be accessed. But how do i do this without touching the code in the
method 'InitializeComponent()', where the ResourceManager seems to be
instantiated. If i do some modifications there the visual designer stops
working properly.

I hope you understand my problem. If you need more details just ask. I
tried to keep it as short as possible.

You see it is nothing vital because there is a way reaching the goal.
But it would be nice if i could write new translations and just copy the
new DLLs and that's it.

Maybe you can give me a hint on this to.

Michael Neßlinger
Mihai N. - 10 Jun 2007 19:48 GMT
> But if i compile and link the .resx file myself into a DLL an put it in
> the proper folder it cannot be accessed.
...
> But it would be nice if i could write new translations and just copy the
> new DLLs and that's it.

This is how it works (jost copy it in place).
My suspicion is that the way you build the DLLs are the cause
(command line switches, parameters, manifests, something there)

Signature

Mihai Nita [Microsoft MVP, Windows - SDK]
http://www.mihai-nita.net
------------------------------------------
Replace _year_ with _ to get the real email

Michael Nesslinger - 10 Jun 2007 22:43 GMT
Mihai N. schrieb:
>> But if i compile and link the .resx file myself into a DLL an put it in
>> the proper folder it cannot be accessed.
[quoted text clipped - 5 lines]
> My suspicion is that the way you build the DLLs are the cause
> (command line switches, parameters, manifests, something there)

Ok, maybe i should give you some more details. I did the following:

1. Created a new Project with Visual Studio.

2. Put some Labels and Buttons on the Form.

3. Made the Form Multilingual and added resources for Englisch and
German in Visual Studio through the Resources Editor.

4. Added some Code to change the language at runtime (see below).

5. Compiled the Project and everything was as i expected.

6. Took the English resource file (text version .resx) and used this to
create a French resource file with an external editor.

7. Compiled the French resx file with the following command:
             ResGen.exe Form1.fr-FR.resx
   into "Form1.fr-FR.resources"

8. Next i linked this file with the following command:
        al.exe /culture:fr-FR    
    /out:bin\Debug\fr-FR\InternationalApplication.resources.dll    
    /embed:Form1.fr-FR.resources    
    /template:bin\Debug\InternationalApplication.exe

9. Then i put resulting DLL in "bin\Debug\fr-FR\"

10. Tried to start. Everything was ok, but instead of loading the
French Resources when i select them the default is loaded.

Here is the only code i added. It is very simple:

public partial class Form1 : Form
   {
       private SortedList cultures;

       public Form1()
       {
           InitializeComponent();
           MoreInitialisation();
       }

       private void MoreInitialisation()
       {
           ResourceManager res = new ResourceManager(typeof(Form1));
           Assembly assembly = Assembly.GetAssembly(typeof(Form1));
           String dir =
        System.IO.Path.GetDirectoryName(assembly.Location);

           cultures = new SortedList();

           foreach(string dname in    
              System.IO.Directory.GetDirectories(dir, "*"))
           {
               try
               {
                   System.Globalization.CultureInfo ci = new
                   CultureInfo(System.IO.Path.GetFileName(dname));
                   try
                   {
                       Assembly satellite =
            assembly.GetSatelliteAssembly(ci);
                       cultures.Add(ci.DisplayName, dname);
                   }
                   catch(FileNotFoundException)
                   {
                   }
               }
               catch(ArgumentException)
               {
               }
           }
           foreach(String info in cultures.Keys)
           {
               this.toolStripComboBox1.ComboBox.Items.Add(((String)info));
           }
       }

       private void button1_Click(object sender, EventArgs e)
       {
           CultureInfo info = new    
CultureInfo(Path.GetFileName((String)cultures[this.toolStripComboBox1.SelectedItem.ToString()]));

           Thread.CurrentThread.CurrentUICulture = info;

           this.Controls.Clear();
           InitializeComponent();
           MoreInitialisation();
       }
   }

My suggestion is that i miss some code for explicitly loading the
satellite assembly in the "button1_Click" method.
Michael Nesslinger - 12 Jun 2007 11:40 GMT
Michael Nesslinger schrieb:

Found the error myself.

[..]

> 7. Compiled the French resx file with the following command:
>              ResGen.exe Form1.fr-FR.resx
[quoted text clipped - 4 lines]
>     /out:bin\Debug\fr-FR\InternationalApplication.resources.dll    
>     /embed:Form1.fr-FR.resources    
This line has to be changed to:

/embed:Form1.fr-FR.resources,InternationalApplication.Form1.fr-FR.resources

>     /template:bin\Debug\InternationalApplication.exe

[..]

The method for changing the language should be altered to the following:

> private void button1_Click(object sender, EventArgs e)
>        {
        Point ps = this.Location;
             Size  sz = this.Size;

>            CultureInfo info = new    
> CultureInfo(Path.GetFileName((String)cultures[this.toolStripComboBox1.SelectedItem.ToString()]));
>
>            Thread.CurrentThread.CurrentUICulture = info;
>
>            this.Controls.Clear();
        this.Events.Dispose();
>            InitializeComponent();
>            MoreInitialisation();
        this.Location = ps;
             this.Size = sz;
>        }

The saving and setting of position and size of the Form is only of some
cosmetic value. But disposing the events is something vital because if
you do not call dispose and keep switching languages the old events are
still there and that is not what we want.
Maybe simply disposing them is not practical in all cases, but you
should get rid of them either by just disposing them or processing them.

Now it works as expected. Thanks to all who helped.

Michael Neßlinger
Michael S. Kaplan [MSFT] - 14 Jun 2007 12:31 GMT
Note that by saving the position and size of controls you actually make the
localization story worse for languages where a localizer changes the layout
for cultural reasons or the size to avoid text clipping.

These properties are considered localizable for a reason; this code ignores
that....

Signature

MichKa [Microsoft]
NLS Collation/Locale/Keyboard Technical Lead
Globalization Infrastructure, Fonts, and Tools
Blog: http://blogs.msdn.com/michkap

This posting is provided "AS IS" with
no warranties, and confers no rights.

> Michael Nesslinger schrieb:
>
[quoted text clipped - 48 lines]
>
> Michael Neßlinger
Michael Nesslinger - 14 Jun 2007 18:14 GMT
Michael S. Kaplan [MSFT] schrieb:
> Note that by saving the position and size of controls you actually make the
> localization story worse for languages where a localizer changes the layout
> for cultural reasons or the size to avoid text clipping.
>
> These properties are considered localizable for a reason; this code ignores
> that....

Yes, you are right. This should not be done with any control at any
time. You have to think carefully about it. I only used it here to keep
the window where the user might have moved it to.
But thanks for this advice.

Michael Neßlinger

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.