Working with localized javascript files

Topics: Customizing Orchard
Mar 1, 2012 at 3:09 PM

I've used a jquery based UI component that comes with a bunch of localized files for the component's labels and messages. I would like the system to use these localized files based on the culture settings of Orchard.

I'm not sure if the orchard Localization system "T()" also works on javascript files but this would not be very useful for me as the UI component comes with its own localization files.

I'm building a custom Field (module) that is using this UI component and in my Editor view I included the en-US localized javascript file. 

Script.Include("localization/jquery-component-en-US").AtFoot();

Question is, how I could get the system to use the other localized files? Is this foreseen in some way?

Developer
Mar 1, 2012 at 6:16 PM
Edited Mar 1, 2012 at 6:17 PM

Orchard actually has excellent support for this scenario right out of the box. The way you do it is by creating a Resource Manifest (which is simply a class that implements IResourceManifestProvider).

As you define your (javascript) resource, you specify which cultures are available for it. Orchard will then include the correct version of your file based on the current culture.

I have written a tutorial that comes across this feature somewhere near the end of the post (search for "SetCultures" using your browser's search tool).

Mar 7, 2012 at 3:00 PM

@sfmskywalker; I followed your tutorial and it has helped me a lot. I believe that I have all the right code now, there's just one thing. 

in my resourcemanifest file I have the following code: 

manifest.DefineScript("Line20.DateTimeRangeField.Localize.TimePicker").SetBasePath(manifest.BasePath + "scripts/localization/").SetUrl("jquery.ui.timepicker.js").SetCultures("nl-BE", "en-US").SetDependencies("Line20.DateTimeRangeField.DateTimePicker");

The code is very straightforward and the same as in your tutorial. The Orchard system replaces the script file with "jquery.ui.timepicker.en-US.js". 

I just have one more problem. I expected that the Orchard system would use the "Default Site Culture" setting from the general tab in the admin. If I change this to "nl-BE" I still get the en-US script. I'm wondering if I'm doing anything wrong here...

Mar 7, 2012 at 3:23 PM
Edited Mar 7, 2012 at 3:24 PM

I just added the following in the web.config

<globalization uiCulture="nl-BE" culture="nl-BE" />

and now it does change the script files. I reckon that this is a bug in Orchard where the system does not apply the Default Site Culture to the current thread.

Changing the web.config is not something I would like to ask from the people who download my module, perhaps they even can't access the web.config...

Developer
Mar 7, 2012 at 5:33 PM

Hi eriklenaerts,

I noticed the same issue as well, but haven't got around it to figure it out where it goes wrong exactly. One way I believe you can work around it is setting the Thread.CurrentCulture based on the culture as configured within the UI. But it would perhaps be best if you changed the code where Orchard uses the Thread.CurrentCulture object instead of the site settings culture (as configured using the backend). If in fact that is the problem of course :)

Mar 7, 2012 at 6:31 PM
Edited Mar 7, 2012 at 6:31 PM

In the ResourceDefinition.cs of the Orchard.UI project has a method called "ResolveUrl". This method uses takes care of changing the url of the resource if Cultures were set on the ResourceDefinition as we did in the ResourceManifest.

In this ResolveUrl method orchard uses the RequireSetting.Culture property to figure out how it should change the Resource url to a localized one. Apparently, there's only one place where this RequireSetting.Culture is set and that is in the Orchard.Core.CoreShapes.WriteResources method:

        private void WriteResources(dynamic Display, TextWriter Output, string resourceType, ResourceLocation? includeLocation, ResourceLocation? excludeLocation) {
            ...
            var defaultSettings = new RequireSettings {
                DebugMode = debugMode,
                Culture = CultureInfo.CurrentUICulture.Name
            };
            ...

So, basically the whole ResolveUrl operation is based on the CurrentUICulture. Now the issue is that nowhere there's code that I found that sets this CurrentUICulture (I would expect a System.Threading.Thread.CurrentUICulture = ... somewhere)

What I did to fix this is the following code:

            ...
            var defaultSettings = new RequireSettings {
                DebugMode = debugMode,
                Culture = _workContext.Value.CurrentCulture
            };
            ...

Although this fixed the ResolveUrl issue, it still doesn't place the whole site in the culture as defined in the general settings. I hope the guys from Orchard read this thread and comment if we're missing a vital piece here.

Developer
Mar 7, 2012 at 9:45 PM

Great finding. Perhaps for now you can fix it by setting the Thread.CurrentUICulture from wherever the WorkContext is initialized (as it is a per request object)? You're probably right that we're missing something here, and there's probably a good reason that no Thread.CurrentUICulture is being set (otherwise we'd surely find it somewhere).