Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Satellite Assembly, ASP.NET language not changing

I'm converting a project to use a satellite assembly. I created a new class library (named "Resources"). All of the default resources are at the root level *.resx. Then there is a folder for each culture.

"en/" with *.en.resx

en-GB/ with *.en-GB.resx

I changed the .resx files Access Modifier to "Public" and changed these settings.

BuildAction: EmbeddedResource
CopyToOutputDirectory: CopyAlways

I made sure the .resx designers *.Designer.cs use the "Resources" namespace.

I added the Class library to an ASP.NET MVC app and in global.asax.cs I have the culture being set as needed.

System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");

I tried adding the al.exe and Resgen.exe commands to the post-build event in the Resources class library.

"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\Resgen.exe" en-GB/MyResourceFile.en-GB.resx "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\al.exe" /t:lib /embed:en-GB/MyResourceFile.en-GB.resources /culture:en-gb /out:Resources.resources.dll

Looking inside the MVC apps bin/ folder there are folders for each language with 3 files:

MyResources.en-GB.Designer.cs, MyResources.en-GB.resx, Resources.resources.dll

The root level only has Resources.dll and Resources.resources.dll but the default language works fine. The second *.resources.dll is due to the post-build event.

When I change the CurrentUICulture it doesn't change the UI language. Before moving the resources out of the App_GlobalResources/ to an external assembly it worked fine (Razor example).

@Resources.MyResources.StringIdentifier 

Looking at the Resource .dlls using .NET Reflector these are the differences.

Satellite Resources: (Project: Resources)
Resources.en_GB.MyResources.en-GB.resources 
App_GlobalResources: (Project MVCApp)
Namespace.MVCApp.App_GlobalResources.MyResources.en-GB.resources

Edit:

After setting the CurrentCulture and UICulture in the global.asax.cs, I tested manually retrieving a ResourceManager which actually worked and retrieved strings in the expected language.

            System.Resources.ResourceManager gStrings =
                new System.Resources.ResourceManager("Resources.MyResources", System.Reflection.Assembly.Load("Resources")); // Resources=Project Name
            string test = gStrings.GetString("TestString"); // WORKS IN GLOBAL.ASAX.CS!!!

I tried the same test in an MVC Controller, but it doesn't work. So the only place the ResourceManager can be retrieved is the Global.asax.cs.

Oddly enough the same test at the UI level in razor would only return the default cultures text! The cultureInfo is correct, but the ResourceManager only returns the default language in the ASP.NET MVC Razor UI. (This is strictly for testing)

    @{  
        System.Globalization.CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentUICulture;
        System.Resources.ResourceManager gStrings =
            new System.Resources.ResourceManager("Resources.MyResource", System.Reflection.Assembly.Load("Resources"));
        string s = gStrings.GetString("Test");    // DOESN'T WORK IN UI
    }

TLDR version:

Converting from Resources (.resx) from App_GlobalResources to satellite assemblies.

The issue at hand.

I can manually call a ResourceManager for the satellite assembly, using the CurrentUICulture language in global.asax and it works as expected, however the same test fails from the UI side and fails in a MVC controller.

The default language works fine, so why doesn't the UI switch languages?

like image 381
lko Avatar asked Nov 13 '22 16:11

lko


1 Answers

If have recently set up a project where the internaltionalization works correctly more or less like you describe.

https://github.com/Jacco/Perpetuality

I switch the language per HTTP request in OnAuthorize in the controller I use as base:

using Perpetuality.Data;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Principal;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;


namespace Perpetuality.Controllers
{
    public partial class BaseController : Controller
    {
        private CultureInfo GetCultureInfo(AuthorizationContext filterContext)
        {
            switch ((string)filterContext.RouteData.Values["language"])
            {
                case "nl":
                    return CultureInfo.CreateSpecificCulture("nl-NL");
                case "en":
                    return CultureInfo.CreateSpecificCulture("en-US");
                case "pt":
                    return CultureInfo.CreateSpecificCulture("pt-PT");
                case "de":
                    return CultureInfo.CreateSpecificCulture("de-DE");
                case "es":
                    return CultureInfo.CreateSpecificCulture("es-ES");
                case "fr":
                    return CultureInfo.CreateSpecificCulture("fr-FR");
                case "it":
                    return CultureInfo.CreateSpecificCulture("it-IT");
                case "jp":
                    return CultureInfo.CreateSpecificCulture("ja-JP");
                default:
                    return CultureInfo.CreateSpecificCulture("en-US");
            }
        }

        protected override void OnAuthorization(AuthorizationContext filterContext)
        {
            Thread.CurrentThread.CurrentCulture = GetCultureInfo(filterContext);
            Thread.CurrentThread.CurrentUICulture = GetCultureInfo(filterContext);

            base.OnAuthorization(filterContext);
        }
    }
}

In my project the RESX files are specified differently than in yours:

BuildAction: EmbeddedResource
CopyToOutputDirectory: DoNotCopy

In my vies I access the strings like this:

@Resources.Home.Index.FacebookButtonCaption

I did setup nothing post or pre build.

In my project the language is always on the url. That was a user can switch language if no appropriate language was initially chosen.

like image 120
Jacco Avatar answered Nov 15 '22 06:11

Jacco