-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
OAM-89: add util function to handle translations in react components (#…
…87)
- Loading branch information
1 parent
39c485f
commit 6d5abd3
Showing
2 changed files
with
326 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/* | ||
* This program is part of the OpenLMIS logistics management information system platform software. | ||
* Copyright © 2017 VillageReach | ||
* | ||
* This program is free software: you can redistribute it and/or modify it under the terms | ||
* of the GNU Affero General Public License as published by the Free Software Foundation, either | ||
* version 3 of the License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; | ||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
* See the GNU Affero General Public License for more details. You should have received a copy of | ||
* the GNU Affero General Public License along with this program. If not, see | ||
* http://www.gnu.org/licenses. For additional information contact [email protected]. | ||
*/ | ||
|
||
(function() { | ||
|
||
'use strict'; | ||
|
||
/** | ||
* @ngdoc service | ||
* @name openlmis-i18n.messageService | ||
* | ||
* @description | ||
* Responsible for retrieving messages. | ||
*/ | ||
angular | ||
.module('openlmis-i18n') | ||
.factory('messageService', messageService); | ||
|
||
var LOCALE_STORAGE_KEY = 'current_locale'; | ||
|
||
messageService.$inject = ['$q', '$rootScope', 'OPENLMIS_MESSAGES', 'DEFAULT_LANGUAGE', 'localStorageService']; | ||
|
||
function messageService($q, $rootScope, OPENLMIS_MESSAGES, DEFAULT_LANGUAGE, localStorageService) { | ||
|
||
var service = { | ||
getCurrentLocale: getCurrentLocale, | ||
populate: populate, | ||
get: get, | ||
formatMessage: formatMessage | ||
}; | ||
|
||
return service; | ||
|
||
/** | ||
* @ngdoc method | ||
* @methodOf openlmis-i18n.messageService | ||
* @name getCurrentLocale | ||
* | ||
* @description | ||
* Returns current locale. | ||
* | ||
* @return {String} current locale | ||
*/ | ||
function getCurrentLocale() { | ||
return localStorageService.get(LOCALE_STORAGE_KEY); | ||
} | ||
|
||
/** | ||
* @ngdoc method | ||
* @methodOf openlmis-i18n.messageService | ||
* @name populate | ||
* | ||
* @description | ||
* Returns current locale. | ||
* | ||
* @param {String} locale (optional) locale to populate | ||
* @return {Promise} Promise | ||
*/ | ||
function populate(locale) { | ||
if (!locale) { | ||
locale = DEFAULT_LANGUAGE; | ||
} | ||
|
||
if (OPENLMIS_MESSAGES[locale]) { | ||
localStorageService.add(LOCALE_STORAGE_KEY, locale); | ||
$rootScope.$broadcast('openlmis.messages.populated'); | ||
return $q.when(); | ||
} | ||
return $q.reject(); | ||
|
||
} | ||
|
||
/** | ||
* @ngdoc method | ||
* @methodOf openlmis-i18n.messageService | ||
* @name get | ||
* | ||
* @description | ||
* Returns message for current locale. | ||
* | ||
* @return {String} display message | ||
*/ | ||
function get() { | ||
var keyWithArgs = Array.prototype.slice.call(arguments); | ||
var displayMessage = keyWithArgs[0]; | ||
var parameters = keyWithArgs[1]; | ||
var currentLocale = getCurrentLocale(); | ||
if (OPENLMIS_MESSAGES[currentLocale] && OPENLMIS_MESSAGES[currentLocale][keyWithArgs[0]]) { | ||
displayMessage = OPENLMIS_MESSAGES[currentLocale][keyWithArgs[0]]; | ||
} | ||
if (parameters) { | ||
//eslint-disable-next-line no-useless-escape | ||
displayMessage = displayMessage.replace(/\$\{([\s]*[^;\s\{]+[\s]*)\}/g, function(_, match) { | ||
return parameters[match.trim()]; | ||
}); | ||
} | ||
return displayMessage; | ||
} | ||
|
||
/** | ||
* @ngdoc method | ||
* @methodOf openlmis-i18n.messageService | ||
* @name formatMessage | ||
* | ||
* @description | ||
* Used in React components to get a translated message from the messageService. | ||
* | ||
* @param {String} key - key of the message | ||
* @param {Object} params - parameters to be used in the message | ||
*/ | ||
function formatMessage(key, params) { | ||
var currentLocale = getCurrentLocale(); | ||
var displayMessage = key; | ||
|
||
if (OPENLMIS_MESSAGES[currentLocale] && OPENLMIS_MESSAGES[currentLocale][key]) { | ||
displayMessage = OPENLMIS_MESSAGES[currentLocale][key]; | ||
|
||
if (params) { | ||
//eslint-disable-next-line no-useless-escape | ||
var REPLACE_PLACEHOLDERS_REGEX = /\$\{([\s]*[^;\s\{]+[\s]*)\}/g; | ||
|
||
displayMessage = displayMessage.replace(REPLACE_PLACEHOLDERS_REGEX, function(_, match) { | ||
var MISSING_PARAM = 'MISSING_PARAM'; | ||
var paramValue = params[match.trim()]; | ||
|
||
return paramValue ? paramValue : MISSING_PARAM; | ||
}); | ||
} | ||
|
||
} else { | ||
console.error('[ERROR]: Translation message not found for: ' + key); | ||
} | ||
|
||
return displayMessage; | ||
} | ||
} | ||
|
||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
/* | ||
* This program is part of the OpenLMIS logistics management information system platform software. | ||
* Copyright © 2017 VillageReach | ||
* | ||
* This program is free software: you can redistribute it and/or modify it under the terms | ||
* of the GNU Affero General Public License as published by the Free Software Foundation, either | ||
* version 3 of the License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; | ||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
* See the GNU Affero General Public License for more details. You should have received a copy of | ||
* the GNU Affero General Public License along with this program. If not, see | ||
* http://www.gnu.org/licenses. For additional information contact [email protected]. | ||
*/ | ||
|
||
describe('MessageService', function() { | ||
|
||
beforeEach(function() { | ||
module('openlmis-i18n', function($provide) { | ||
$provide.constant('DEFAULT_LANGUAGE', 'en'); | ||
$provide.constant('MISSING_PARAM', 'MISSING_PARAM'); | ||
|
||
$provide.constant('OPENLMIS_MESSAGES', { | ||
en: { | ||
'language.name': 'English', | ||
sample: 'message', | ||
messageWithParam: 'hello ${name}!', | ||
messageWithParams: 'Object with id: ${id}, status: ${status}', | ||
messageWithParams2: 'Object with id: ${0}, status: ${1}' | ||
}, | ||
test: { | ||
'language.name': 'Test', | ||
sample: 'foo' | ||
} | ||
}); | ||
}); | ||
|
||
inject(function($injector) { | ||
this.$rootScope = $injector.get('$rootScope'); | ||
this.messageService = $injector.get('messageService'); | ||
this.localStorageService = $injector.get('localStorageService'); | ||
}); | ||
|
||
spyOn(this.localStorageService, 'get').andReturn('en'); | ||
spyOn(this.localStorageService, 'add'); | ||
spyOn(this.$rootScope, '$broadcast'); | ||
}); | ||
|
||
it('loads a default language when populated without any parameters', function() { | ||
this.messageService.populate(); | ||
|
||
expect(this.localStorageService.add).toHaveBeenCalledWith('current_locale', 'en'); | ||
}); | ||
|
||
it('returns existing translation', function() { | ||
expect(this.messageService.get('sample')).toBe('message'); | ||
}); | ||
|
||
it('returns the message string when a translation doesn\'t exist', function() { | ||
expect(this.messageService.get('foobar')).toBe('foobar'); | ||
}); | ||
|
||
it('returns the message string with parameter', function() { | ||
var person = { | ||
name: 'Jane' | ||
}; | ||
var expected = 'hello Jane!'; | ||
|
||
expect(this.messageService.get('messageWithParam', person)).toBe(expected); | ||
}); | ||
|
||
it('returns the message string with multiple parameters', function() { | ||
var object = { | ||
id: '123', | ||
status: 'NEW' | ||
}; | ||
var expected = 'Object with id: 123, status: NEW'; | ||
|
||
expect(this.messageService.get('messageWithParams', object)).toBe(expected); | ||
}); | ||
|
||
it('returns the message string with parameters in array', function() { | ||
var array = ['123', 'NEW']; | ||
var expected = 'Object with id: 123, status: NEW'; | ||
|
||
expect(this.messageService.get('messageWithParams2', array)).toBe(expected); | ||
}); | ||
|
||
it('can change the current locale', function() { | ||
this.messageService.populate('test'); | ||
this.localStorageService.get.andReturn('test'); | ||
|
||
expect(this.localStorageService.add).toHaveBeenCalledWith('current_locale', 'test'); | ||
expect(this.messageService.get('sample')).toBe('foo'); | ||
}); | ||
|
||
it('broadcasts an event when the locale is successfully changed', function() { | ||
this.messageService.populate('test'); | ||
|
||
expect(this.$rootScope.$broadcast).toHaveBeenCalledWith('openlmis.messages.populated'); | ||
}); | ||
|
||
it('resolves a promise when the locale is changed', function() { | ||
var success = false; | ||
|
||
var promise = this.messageService.populate('test'); | ||
promise.then(function() { | ||
success = true; | ||
}); | ||
|
||
this.$rootScope.$apply(); | ||
|
||
expect(success).toBe(true); | ||
}); | ||
|
||
it('rejects the promise when locale isn\'t changed', function() { | ||
var success = false; | ||
|
||
var promise = this.messageService.populate('foo'); | ||
promise.catch(function() { | ||
success = true; | ||
}); | ||
|
||
this.$rootScope.$apply(); | ||
|
||
expect(success).toBe(true); | ||
}); | ||
|
||
describe('formatMessage', function() { | ||
it('returns the translated message with parameters', function() { | ||
var key = 'messageWithParam'; | ||
var params = { | ||
name: 'John' | ||
}; | ||
var expected = 'hello John!'; | ||
|
||
var result = this.messageService.formatMessage(key, params); | ||
|
||
expect(result).toBe(expected); | ||
}); | ||
|
||
it('returns the translated message with missing parameters', function() { | ||
var key = 'messageWithParam'; | ||
var params = { | ||
age: 25 | ||
}; | ||
var expected = 'hello MISSING_PARAM!'; | ||
|
||
var result = this.messageService.formatMessage(key, params); | ||
|
||
expect(result).toBe(expected); | ||
}); | ||
|
||
it('returns the translated message if key exists but no parameters are passed', function() { | ||
var key = 'sample'; | ||
|
||
var expected = 'message'; | ||
|
||
var result = this.messageService.formatMessage(key); | ||
|
||
expect(result).toBe(expected); | ||
}); | ||
|
||
it('returns the key when translation is not found', function() { | ||
var key = 'nonExistentKey'; | ||
var params = { | ||
name: 'John' | ||
}; | ||
var expected = 'nonExistentKey'; | ||
|
||
var result = this.messageService.formatMessage(key, params); | ||
|
||
expect(result).toBe(expected); | ||
}); | ||
}); | ||
}); |