how to get browser language via script include or function call

Eleven_TW
Tera Contributor

gs.getSession().getLanguage() will retrieve current session pre-defined language but I want to get browser langugage/language code as kind of backup.

 

navigator.language || navigator.userLanguage seems like not working since it will show error of navigator is not defined.

 

also tried to create a new class of script include, but seems like not working either as following:

var BrowserLocaleUtil = Class.create();
BrowserLocaleUtil.prototype = {
    initialize: function() {},

    getBrowserLocale: function(request) {
    var acceptLanguage = request.getHeader('Accept-Language');

    if (acceptLanguage) {
        var languageTag = acceptLanguage.split(',')[0];

        return languageTag;
    } else {
        return 'en';
    }
},

type: 'BrowserLocaleUtil'
};

and call in other script
var browserLocaleUtil = new BrowserLocaleUtil();

var browserLocale = browserLocaleUtil.getBrowserLocale(current.request);

 

Please help any JavaScript functions to retrieve the browser language code since there is potential missing from either service now user table or current session language set.

7 REPLIES 7

Eleven_TW
Tera Contributor

Hi -O-,

Thank you so much for your details.

 

Everything works fine in background script, I can get locale using the following:

var acceptLanguage = GlideTransaction.get().getRequest().getHeader('Accept-Language');

var locale = acceptLanguage.split(',').shift();

gs.info(acceptLanguage);

=> 

*** Script: en-US,en;q=0.9

But after I created global script include as attached screenshot

 

and call it in my application script include via:

var browserUtils = new global.BrowserUtils();
var expectedLocale =  browserUtils.getBrowserLocale();

It shows error:

*** Script: Falied to get browser locale {"message":"Cannot convert null to an object.","rhinoException":{}}: no thrown error

 

Thanks in advance for your help!

Eleven_TW
Tera Contributor

Hi János,

Thank you so much for your details.

 

When I run it in background script, everything works fine and I can get the following result:

1. running in Global scope with following:

var acceptLanguage= GlideTransaction.get().getRequest().getHeader('Accept-Language');
var languageTag = acceptLanguage.split(',').shift();

gs.log("acceptLanguage " + acceptLanguage);

=>

*** Script: acceptLanguage en-US,en;q=0.9

2. running in my application scope to call the global script include:

var utils = new global.BrowserUtils();

var language = utils.getBrowserLocale();

gs.info(language);

=>

en-US

 

But when I call in my application scope script include, it always fails with error

"message":"Cannot convert null to an object."

because GlideTransaction.get().getRequest() is always null

 

do you know the possible root cause?

 

Thank you so much in advance!

 

 

What exactly triggers the scoped Script Include that calls the global Script Include?

I mean not every process/transaction in ServiceNow has an associated request.

Perhaps that is what is going on here.

In any case I would re-write the Script Include to account for the possibility that any of the methods returned invalid result, something like:

var BrowserLocaleUtil = Class.create();

BrowserLocaleUtil.pipe = function (rv, fn) {
	return rv == null ? undefined : fn(rv);
};

BrowserLocaleUtil.prototype = {

	'initialize': function () {

	},

	'getBrowserLocale': function () {
		return this._getAcceptLanguage() || this._getDefaultLanguage();
	},

	'type': 'BrowserLocaleUtil',

	'_getAcceptLanguage': function () {
		return [
			this._getGlideTransaction,
			this._getGlideTransactionRequest,
			this._getGlideTransactionRequestHeader('Accept-Language'),
			this._getBaseLanguageTag
		].reduce(BrowserLocaleUtil.pipe, {});
	},

	'_getBaseLanguageTag': function (data) {
		return String(data).trim().split(/\s*,\s*/g).shift();
	},

	'_getDefaultLanguage': function () {
		return '' + gs.getProperty('glide.sys.language', 'en');
	},

	'_getGlideTransaction': function () {
		return GlideTransaction.get();
	},

	'_getGlideTransactionRequest': function (data) {
		return data.getRequest();
	},

	'_getGlideTransactionRequestHeader': function (headerName) {
		return function (data) {
			return data.getHeader(headerName);
		};
	},

};

This is necessary because other than the above mentioned situation (there is no request in the transaction) even your script (but this one too) can be called from Scripts - Background both while running in global scope or in a private scope.