3

!! this is NOT about localisation of the App Web
Its about getting an incorrect response from the HostWeb when using get_title() !!

Can someone please explain me where I go wrong with the testcode (all the way the bottom)

I develop https://www.365csi.nl/vm365com Apps [using Microsoft Napa! so I can not do anything with .Net code] which Create Calculated Columns in the Host-Web; so in the Formulas I need to use Localized DisplayNames on non-english sites.

MSDN documentation for Field.get_title() says: Gets or sets value that specifies the display name of the field.

But On the same non-english Subsite get_title() returns different results when run directly in the site compared to when run from an App.

Steps to reproduce:

Run code in a teamsite

  1. Create a non-english Locale subsite I used German in my example, its not my own language but can read it
  2. Run the script below in Chrome Snippets

This produces the results I expect, get_title() gets me the localized DisplayName

Run code from an App-web

  1. [install an (english¿) App with read rights in]
  2. Now open the App in that same subsite (now Host-web)
  3. Run the script below in Chrome Snippets the script is now accessing the subsite through the App-web

Now get_title() returns me the DisplayName as if the site was an English Locale;

!! extracting the DisplayName from the SchemaXml clearly shows the correct DisplayName !!

It looks to me like get_title() returns the Locale DisplayName of the App Web instead of the Host-Web.. (I have not tested what happens with an App which is not in english.. couldn't find one; and with Napa I can only create english Apps)

Test code

Code to be run as Chrome Snippets (or any way you want it)

try-catch is used to try App code first; if it fails it defaults to the current ClientContext

    var listName='Tasks';
    var reportDIV=document.getElementById('DeltaPlaceHolderMain');
    var listTitle='<h1>'+listName+'</h1>';
    reportDIV.innerHTML=listTitle;
    var context,web;
    JSRequest.EnsureSetup();
    try{
        context = new SP.ClientContext(decodeURIComponent(JSRequest.QueryString["SPAppWebUrl"]));
        var appContextSite = new SP.AppContextSite(context, decodeURIComponent(JSRequest.QueryString["SPHostUrl"]));
        web = appContextSite.get_web();
    } catch(e){
        context = new SP.ClientContext.get_current();
        web=context.get_web();    
    }
    listTitle+='<h2>context.get_url() = '+context.get_url()+'</h2>';
    var fields=web.get_lists().getByTitle( listName ).get_fields();
    context.load(fields);
    context.executeQueryAsync(
        function(){
            var fieldEnumerator = fields.getEnumerator();
            var rows=0,table='<tr><td><b>get_internalName()</b></td><td><b>get_title()</b></td><td><b>DisplayName from get_schemaXml()</b></td></tr>';
            while (fieldEnumerator.moveNext()) {
                var field=fieldEnumerator.get_current();
                var DisplayName = field.get_schemaXml().split('DisplayName="')[1].split('"')[0];
                var Title=field.get_title();
                Title = DisplayName!=Title ? '<b style="color:red">'+Title+'</b>' : Title;
                var cols = []; cols.push( field.get_internalName() , Title , DisplayName );
                table+='<tr style="background-color:#E0E7F'+(rows++%2?1:10)+'"><td>'+cols.join('</td><td>')+'</td></tr>';
            }
            reportDIV.innerHTML=listTitle+'<table width=100%>'+table+'</table>';
        }
    ,
        function( sender,args){ alert(args.get_message())}
    );
2
  • I thought an app would stay the locale it was install under, and disregards user/site locale after that. You can get the field title for a specific locale like this: var resource = field.get_titleResource();c.load(resource);c.executeQueryAsync(function() { console.log(resource.getValueForUICulture('no').get_value())})
    – eirikb
    Commented Feb 25, 2015 at 13:45
  • Why not try a SharePoint-hosted app? I cannot test this in my environment, but a SharePoint-hosted app should mimic the host site settings. SharePoint-hosted apps can only use html/JavaScript. ASP/C# are not allowed, so it is similar to a NAPA app.
    – wjervis
    Commented Mar 2, 2015 at 15:21

3 Answers 3

2
+50

SP.Field.title property returns display name of the field based on the language that is used on the current site (SP.Web.language property). So, i believe that your assumption:

It looks to me like get_title() returns the Locale DisplayName of the App Web instead of the Host-Web..

is correct.

In order to return field display name for specific locale SP.Field.TitleResource property is intended. The following example demonstrates how to return field display name for the current locale:

var titleRes = field.get_titleResource();
var  titleResVal = titleRes.getValueForUICulture(_spPageContextInfo.currentCultureName);

Modified example

var listName='Tasks';
var reportDIV=document.getElementById('DeltaPlaceHolderMain');
var listTitle='<h1>'+listName+'</h1>';
reportDIV.innerHTML=listTitle;
var context,web;
JSRequest.EnsureSetup();
try{
    context = new SP.ClientContext(decodeURIComponent(JSRequest.QueryString["SPAppWebUrl"]));
    var appContextSite = new SP.AppContextSite(context, decodeURIComponent(JSRequest.QueryString["SPHostUrl"]));
    web = appContextSite.get_web();
} catch(e){
    context = new SP.ClientContext.get_current();
    web=context.get_web();    
}
listTitle+='<h2>context.get_url() = '+context.get_url()+'</h2>';
var fields=web.get_lists().getByTitle( listName ).get_fields();
context.load(fields,'Include(Title,TitleResource,SchemaXml,InternalName)');
context.executeQueryAsync(
    function(){
        var result = [];
        var e = fields.getEnumerator();
        while (e.moveNext()) {
            var field = e.get_current();
            var displayName = field.get_schemaXml().split('DisplayName="')[1].split('"')[0];
            var titleRes = field.get_titleResource();
            var  titleResVal = titleRes.getValueForUICulture(_spPageContextInfo.currentCultureName);
            result.push({'TitleResource': titleResVal,'DisplayName': displayName,'InternalName': field.get_internalName()}); 
        }
        context.executeQueryAsync(function(){
            var output = '<tr><td><b>get_internalName()</b></td><td><b>get_title()</b></td><td><b>DisplayName from get_schemaXml()</b></td></tr>';
            for(var row = 0; row < result.length;row++) {
                 var displayName = result[row].DisplayName;
                 var titleRes = result[row]['TitleResource'].get_value();
                 var titleResHtml = displayName != titleRes ? '<b style="color:red">' + titleRes + '</b>' : titleRes;
                 var cols = []; cols.push( result[row].InternalName , titleResHtml , displayName );
                 output += '<tr style="background-color:#E0E7F'+(row++%2?1:10)+'"><td>'+cols.join('</td><td>')+'</td></tr>';
            }
            reportDIV.innerHTML=listTitle+'<table width=100%>'+output+'</table>';
        },
        function(){
            reportDIV.innerHTML= String.format('<div width=100%>An error occured: {0}</div>',args.get_message());
        });
    },
    function( sender,args){ 
       reportDIV.innerHTML= String.format('<div width=100%>An error occured: {0}</div>',args.get_message());
    }
);

Update

The following example demonstrates how to retrieve field display names based on the language that is used on the host web.

Key points:

  • SP.Web.get_language() method is used to determine host web site language (lcid)
  • since SP.Field.TitleResource.getValueForUICulture method expects UI cutlture name, SP.ServerSettings.getGlobalInstalledLanguages method is used for getting languages info

Example:

var listName='Tasks';
var reportDIV=document.getElementById('DeltaPlaceHolderMain');
var listTitle='<h1>'+listName+'</h1>';
reportDIV.innerHTML=listTitle;
var context,web;
JSRequest.EnsureSetup();
try{
    context = new SP.ClientContext(decodeURIComponent(JSRequest.QueryString["SPAppWebUrl"]));
    var appContextSite = new SP.AppContextSite(context, decodeURIComponent(JSRequest.QueryString["SPHostUrl"]));
    web = appContextSite.get_web();
} catch(e){
    context = new SP.ClientContext.get_current();
    web=context.get_web();    
}


var languages = SP.ServerSettings.getGlobalInstalledLanguages(context,15); //Retrieve all installed languages
context.load(web,'Language'); //Retrieve host web language


listTitle+='<h2>context.get_url() = '+context.get_url()+'</h2>';
var fields=web.get_lists().getByTitle( listName ).get_fields();
context.load(fields,'Include(Title,TitleResource,SchemaXml,InternalName)');
context.executeQueryAsync(
    function(){

        //find host web language info
        var language = languages.filter(function(l) {
                      return web.get_language() === l.get_lcid(); 
                   })[0];
        var langTag = language.get_languageTag();           

        var result = [];
        var e = fields.getEnumerator();
        while (e.moveNext()) {
            var field = e.get_current();
            var displayName = field.get_schemaXml().split('DisplayName="')[1].split('"')[0];
            var titleRes = field.get_titleResource();
            var  titleResVal = titleRes.getValueForUICulture(langTag);
            result.push({'TitleResource': titleResVal,'DisplayName': displayName,'InternalName': field.get_internalName()}); 
        }
        context.executeQueryAsync(function(){
            var output = '<tr><td><b>get_internalName()</b></td><td><b>get_title()</b></td><td><b>DisplayName from get_schemaXml()</b></td></tr>';
            for(var row = 0; row < result.length;row++) {
                 var displayName = result[row].DisplayName;
                 var titleRes = result[row]['TitleResource'].get_value();
                 var titleResHtml = displayName != titleRes ? '<b style="color:red">' + titleRes + '</b>' : titleRes;
                 var cols = []; cols.push( result[row].InternalName , titleResHtml , displayName );
                 output += '<tr style="background-color:#E0E7F'+(row++%2?1:10)+'"><td>'+cols.join('</td><td>')+'</td></tr>';
            }
            reportDIV.innerHTML=listTitle+'<table width=100%>'+output+'</table>';
        },
        function(){
            reportDIV.innerHTML= String.format('<div width=100%>An error occured: {0}</div>',args.get_message());
        });
    },
    function( sender,args){ 
       reportDIV.innerHTML= String.format('<div width=100%>An error occured: {0}</div>',args.get_message());
    }
);
3
0

Just add German localization in a Visual Studio for your app. Double click on AppMinifest.xml. Add localization tab. New Resource file will be created. You can leave it empty. Then re-add your app. And now all should work fine.

7
  • When you will be prompted to confirm app installation (window with app requested permissions), you can select app localization (from those which presented in app manifest file).
    – BioGeneZ
    Commented Feb 25, 2015 at 13:40
  • I just look into the Napa, and can't find any options like in a Visual Studio, to add supported localization. You should use Visual Studio.
    – BioGeneZ
    Commented Feb 25, 2015 at 13:51
  • My App itself is English (and thats the only language I want ) and needs to support ANY language of the HostWeb. For me as non .Net programmer it seems a bit weird to require Resource files... How many languages are there? Does Microsoft require us to add them all in the AppManifest? I fully comprehend the AppManifest stuff if one requires Localized Apps (NAPA only does English). This Resource answer also does not explain why the correct localized information is in the SchemaXml (where I now extract it from). Again; I don't care about the language of the App itself.. its about the HostWeb Commented Feb 26, 2015 at 16:11
  • The correct info in SchemaXml, because it's just xml, and localization isn't applied for it. But returned field title is localized. Unfortunately, you should select localization when you install an app. And yes, you can add resources (for all languages (there are list of available languages in a visual studio, which you can add to your app)). If you will add all of them, then when your app will be installed, in a prompted window will be selected right language. (sorry for my bad English) (p.s.: you can't add resources with NAPA tool, only English)
    – BioGeneZ
    Commented Feb 26, 2015 at 16:24
  • Also, you can download your app file. Because app is an archive, i think, that you can extract appManifext.xml, then fix it to support many languages. (p.s.: I have not tried this solution)
    – BioGeneZ
    Commented Feb 26, 2015 at 16:29
-3

Found my old post i answered to regarding this, from when i had a similar issue. Please see if below helps.

Language in SharePoint that is Displayed to the user is based on a the HTTP Request Header ["Accepted Languages"] or the SharePoint language cookie if the user selects a specific language in the SharePoint language selection menu. This menu is only shown when activating one or more alternative languages on a site collection.

If you want to change language in the background for a specific part of the code then you will need to set the current running threads to the language you want to use.

System.Threading.Thread.CurrentThread.CurrentUICulture.Name="no" 
System.Threading.Thread.CurrentThread.CurrentCulture.Name="no"

By default Ajax requests for example, will fall back to the site collections default language, the language you selected as default when creating the site collection. On normal page requests it will use the users selected language(cookie or Accepted Languages)

And as mentioned before SPWeb.Local only has a public Get not a Set.

Old post

3
  • I am using Microsoft Napa, am not a .Net developer so can't do anything with this code. I am not changing Locale. The same (German) Site used produces different results. And Your answer does not explain the difference between get_title() and the (correct) DisplayName in schemaXML which was acquired in the same call. Commented Jan 30, 2015 at 10:47
  • So for your first issue. Did you try setting the Accepted Languages Header to German language and culture? The other question is something that comes back to SharePoint's MUI handling. where you need to use Resource specific titles of things. Which always Servers the default title in the default language, unless Accepted Languages or cookies says something else, or your thread has been manually changed. But that i only have examples in C# so it would be no good to you as you describe above.
    – Robban1980
    Commented Feb 2, 2015 at 5:53
  • Tnx for looking into it. Indeed I can not do anything with C#. The 2 two runs use the same Browser session to the same SharePoint Office365 server/site. The only difference is: one is called from the current site and the other thru the App-web. And the App-Web is English; nevertheless this behaviour does not make sense; now get_title() is useless. I have rewritten the code to not use get_title() and extract the correct DisplayName from the SchemaXml. I'll leave the question open, as there is no answer to the Why? Commented Feb 3, 2015 at 9:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.