locked
Globalization and localization of data RRS feed

  • Question

  • I am using ADO.Net Data Services to retrieve data for a WPF application. I am not using the Entity Framework. Some of the data that I am retrieving is data used to validate input or used to populate combo boxes with possible values. I'd like to be able to localize this data on the server side. So if the wpf app is running on French box when I call to get data using ADO.Net Data Services I want my code that retrieves the data and returns it to be able to localize the data to that French culture. Is there any way with ADO.Net Data Services to communicate the client's locale information to the server when making a call to retrieve data? I have not found any good way to do this and I haven't been able to find any posts online describing this.
    Monday, June 22, 2009 8:38 PM

Answers

  • Hi Pags,
     I apologize for the late response.
     I am no expert in globalization / localization on the server-side , but it looks like the data regarding the user locale is found in the Accept-Language header that the client sends in a request to the server.


    Per EntitySet level localization
     On the server-side you can write a query interceptor that inspects this value and adds a subsequent filter to only return data in that language.

    /Customers

    Accept-Language: en-US


    [QueryInterceptor("Customers")]
    public Expression<Func<Customers,bool>> OnQueryCustomers() {

    string acceptLanguage = WebOperationContext.Current.IncomingRequest.Headers["Accept-Language"].ToString();

    return  customerData => customerData.Where( cust => cust.LanguageDiscriminator == acceptLanguage );
    }

    Service wide Localization
    override the OnStartProcessingRequest method to change the culture in which a request will be processed and also error/diagnostic messages
    are returned to the client.

    protected override void OnStartProcessingRequest(ProcessRequestArgs args) {
    string acceptLanguage = WebOperationContext.Current.IncomingRequest.Headers["Accept-Language"].ToString();

    System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(acceptLanguage);


    }

    This way , you wont need to pass any additional data in the query string and can do the hand-shake via the headers.

    Phani Raj Astoria http://blogs.msdn.com/PhaniRaj
    Thursday, June 25, 2009 5:12 PM
    Moderator

All replies

  • Ok, I'll add some more info see if anyone has any thoughts! In ASP.Net 2.0 and above the web.config file contains a <globalization> tag. If you add this to your site and set the culture and cultureui attributes to Auto then ASP.Net will pick up the culture info from the users' browser and set your thread to run using that info so your web site runs using the same culture info as the user's browser and localization stuff works really nicely and easily. Since ADO.Net Data Services seems to utilize the ASP.Net engine to process its requests I was hoping that maybe I could use a web.config with a <globalization> tag in the same way and my thread would pick up the culture info of the client. This does not seem to work though. Right now I only need the culture info for queries. As an example I have a combo box in my app and I get the data for that combo box from my data service. So I'm returning an IQueryable that has the text and value data to populate my combo box with the available options. What I'd like to do is based on the client culture localize the text values that are returned from the data service so that the end user sees strings in their own language in the combo box. I don't want to do this on the client side because I don't want my UI to have to know what the possible values are for the combo box. That kind of defeats the purpose of a data-driven app.

    So, right now since it is just queries for this data that matters what I am doing is when I build up my data services url to do the query for this data I am appending a query string with the culture info from the client, like http://dataservice.srv/mycomboboxdata?cid=enUS, and then in my data service I am pulling the cid query string value and using that to set my thread culture info and then localizing my strings. This feels like a bit of a hack to me and not necessarily the best way to do this so I'm just wondering if anyone else has done this or if there is any better, more built-in, way to do this with ADO.Net data services.
    Thursday, June 25, 2009 1:52 PM
  • Hi Pags,
     I apologize for the late response.
     I am no expert in globalization / localization on the server-side , but it looks like the data regarding the user locale is found in the Accept-Language header that the client sends in a request to the server.


    Per EntitySet level localization
     On the server-side you can write a query interceptor that inspects this value and adds a subsequent filter to only return data in that language.

    /Customers

    Accept-Language: en-US


    [QueryInterceptor("Customers")]
    public Expression<Func<Customers,bool>> OnQueryCustomers() {

    string acceptLanguage = WebOperationContext.Current.IncomingRequest.Headers["Accept-Language"].ToString();

    return  customerData => customerData.Where( cust => cust.LanguageDiscriminator == acceptLanguage );
    }

    Service wide Localization
    override the OnStartProcessingRequest method to change the culture in which a request will be processed and also error/diagnostic messages
    are returned to the client.

    protected override void OnStartProcessingRequest(ProcessRequestArgs args) {
    string acceptLanguage = WebOperationContext.Current.IncomingRequest.Headers["Accept-Language"].ToString();

    System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(acceptLanguage);


    }

    This way , you wont need to pass any additional data in the query string and can do the hand-shake via the headers.

    Phani Raj Astoria http://blogs.msdn.com/PhaniRaj
    Thursday, June 25, 2009 5:12 PM
    Moderator
  • Thanks. This was what I was looking for but it doesn't quite work as I expected. I added the code to the OnStartProcessingRequest override as you show above but this didn't get called as I expected it would. For example if I make a call to query for data the property in my data service that returns the IQueryable gets called before this OnStartProcessingRequest override so I don't end up setting the thread culture until after my query is already done. I would've thought OnStartProcessingRequest would get called before anything else but it apparently does not. I also discovered that the dataservices client code does not automatically add the Accept-Language header to the request. So I did the following things to get this working the way I need:

    1. On the client side I derived my own class off DataServiceContext and added an event handler for the SendingRequest event and in that event handler I added the Accept-Language header to the request. This ensures, I think, that every data service request sent from my client has the culture info in the headers.
    2. On the server side I created a base class that all of my data service data classes derive from. In my base class constructor I pull the request header as you show above and then set the thread culture info. Incidentally this class also implements the IUpdatable interface in a generic fashion so any class I derive off it gets most of the support needed to handle creates, inserts, and deletes for free.
    3. Any data service I write I derive off the base class I created in 2.

    I think this does what I want it to do and all the implementation is at least in generic base classes so I don't have to worry about it in any new stuff I write. We'll see. I've got some unit testing yet to do to make sure everything works.

    Thanks.
    Friday, June 26, 2009 1:44 PM
  • Hi Pags,
      Yes , OnStartProcessingRequest being called after the IQueryable has been accessed is an unfortunate bug .
     You can try overriding the CreateDataSource method in the base data service to set the Accept-Language header.
     If you face any further issues , please do chime in .
       
    Phani Raj Astoria http://blogs.msdn.com/PhaniRaj
    Friday, June 26, 2009 6:26 PM
    Moderator