Skip to content
This repository has been archived by the owner on Jan 29, 2024. It is now read-only.

Commit

Permalink
feat(service): add uniformLanguageTagResolver
Browse files Browse the repository at this point in the history
This introduces `$translateProvider.uniformLanguageTag()` extending the
already existing `$translateProvider.determinePreferredLanguage()` based
on the browser's locales. The goal of this feature is getting an uniform
language tag regardless of different browsers' language tags.

We are starting with threes different kinds:

* standard - just like the behavior you already know
 * en_US -> en_US
 * en-US -> en_US
 * en-us -> en_us
 * en => en

* java (everything after a 2nd underscore will be omitted)
 * en_US -> en_US
 * en-US -> en_US
 * en-us -> en_US (different to standard)
 * en => en

* bcp47 (everything after a 2nd hyphen will be omitted)
 * en_US -> en-US
 * en-US -> en-US
 * en-us -> en-US
 * en -> en

http://tools.ietf.org/html/bcp47
  • Loading branch information
knalli committed Apr 26, 2015
1 parent f995fa6 commit b534e1a
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 5 deletions.
85 changes: 81 additions & 4 deletions src/service/translate.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
*
*/
angular.module('pascalprecht.translate')
.constant('pascalprechtTranslateOverrider', {})
.provider('$translate', $translate);

function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvider) {
function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvider, pascalprechtTranslateOverrider) {

'use strict';

Expand All @@ -37,12 +38,34 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
NESTED_OBJECT_DELIMITER = '.',
loaderCache,
directivePriority = 0,
statefulFilter = true;
statefulFilter = true,
uniformLanguageTagResolver = 'standard',
languageTagResolver = {
standard: function (tag) {
return (tag || '').split('-').join('_');
},
java: function (tag) {
var temp = (tag || '').split('-').join('_');
var parts = temp.split('_');
return parts.length > 1 ? (parts[0].toLowerCase() + '_' + parts[1].toUpperCase()) : temp;
},
bcp47: function (tag) {
var temp = (tag || '').split('_').join('-');
var parts = temp.split('-');
return parts.length > 1 ? (parts[0].toLowerCase() + '-' + parts[1].toUpperCase()) : temp;
}
};

var version = 'x.y.z';

// tries to determine the browsers language
var getFirstBrowserLanguage = function () {

// internal purpose only
if (angular.isFunction(pascalprechtTranslateOverrider.getLocale)) {
return pascalprechtTranslateOverrider.getLocale();
}

var nav = $windowProvider.$get().navigator,
browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'],
i,
Expand Down Expand Up @@ -72,7 +95,11 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide

// tries to determine the browsers locale
var getLocale = function () {
return (getFirstBrowserLanguage() || '').split('-').join('_');
var locale = getFirstBrowserLanguage() || '';
if (languageTagResolver[uniformLanguageTagResolver]) {
locale = languageTagResolver[uniformLanguageTagResolver](locale);
}
return locale;
};
getLocale.displayName = 'angular-translate/service: getLocale';

Expand Down Expand Up @@ -678,6 +705,56 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
return this;
};

/**
* @ngdoc function
* @name pascalprecht.translate.$translateProvider#uniformLanguageTag
* @methodOf pascalprecht.translate.$translateProvider
*
* @description
* Tells angular-translate which language tag should be used as a result when determining
* the current browser language.
*
* This setting must be set before invoking determinePreferredLanguage.
*
* The resolver currently supports:
* * default
* (traditionally: hyphens will be converted into underscores, i.e. en-US => en_US)
* en-US => en_US
* en_US => en_US
* en-us => en_us
* * java
* like default, but the second part will be always in uppercase
* en-US => en_US
* en_US => en_US
* en-us => en_US
* * BCP 47 (RFC 4646 & 4647)
* en-US => en-US
* en_US => en-US
* en-us => en-US
*
* See also:
* * http://en.wikipedia.org/wiki/IETF_language_tag
* * http://www.w3.org/International/core/langtags/
* * http://tools.ietf.org/html/bcp47
*
* @param {string|object} options - options (or standard)
* @param {string} options.standard - valid values are 'default', 'bcp47', 'java'
*/
this.uniformLanguageTag = function (options) {

if (!options) {
options = {};
} else if (angular.isString(options)) {
options = {
standard: options
};
}

uniformLanguageTagResolver = options.standard;

return this;
};

/**
* @ngdoc function
* @name pascalprecht.translate.$translateProvider#determinePreferredLanguage
Expand All @@ -693,7 +770,7 @@ function $translate($STORAGE_KEY, $windowProvider, $translateSanitizationProvide
* `[lang]` depending on what the browser provides.
*
* Use this method at your own risk, since not all browsers return a valid
* locale.
* locale (note: have a look at #uniformLanguageTag().
*
* @param {Function=} fn Function to determine a browser's locale
*/
Expand Down
144 changes: 143 additions & 1 deletion test/unit/service/translate.determineLocale.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,149 @@ describe('pascalprecht.translate', function () {
});
});
});

describe('using resolver "default"', function () {
describe('should resolve to en-US to en_US', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en-US'; };
$translateProvider.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en_US');
}));
});

describe('should resolve to en_US to en_US', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en_US'; };
$translateProvider.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en_US');
}));
});

describe('should resolve to en-us to en_us', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en-us'; };
$translateProvider.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en_us');
}));
});

describe('should resolve to en to en using', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en'; };
$translateProvider.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en');
}));
});
});

describe('using resolver "java"', function () {
describe('should resolve to en-US to en_US', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en-US'; };
$translateProvider
.uniformLanguageTag('java')
.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en_US');
}));
});

describe('should resolve to en_US to en_US', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en_US'; };
$translateProvider
.uniformLanguageTag('java')
.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en_US');
}));
});

describe('should resolve to en-us to en_US', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en-us'; };
$translateProvider
.uniformLanguageTag('java')
.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en_US');
}));
});

describe('should resolve to en to en using', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en'; };
$translateProvider
.uniformLanguageTag('java')
.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en');
}));
});
});

describe('using resolver "bcp47"', function () {
describe('should resolve to en-US to en-US', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en-US'; };
$translateProvider
.uniformLanguageTag('bcp47')
.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en-US');
}));
});

describe('should resolve to en_US to en-US', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en_US'; };
$translateProvider
.uniformLanguageTag('bcp47')
.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en-US');
}));
});

describe('should resolve to en-us to en-US', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en-us'; };
$translateProvider
.uniformLanguageTag('bcp47')
.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en-US');
}));
});

describe('should resolve to en to en using', function () {
beforeEach(module('pascalprecht.translate', function ($translateProvider, $provide, pascalprechtTranslateOverrider) {
pascalprechtTranslateOverrider.getLocale = function () { return 'en'; };
$translateProvider
.uniformLanguageTag('bcp47')
.determinePreferredLanguage();
}));
it('test', inject(function ($window, $translate) {
expect($translate.use()).toEqual('en');
}));
});
});

});
});

});

0 comments on commit b534e1a

Please sign in to comment.