diff --git a/dist/angular-gettext.js b/dist/angular-gettext.js index 8280b65..38ea6bd 100644 --- a/dist/angular-gettext.js +++ b/dist/angular-gettext.js @@ -37,6 +37,19 @@ angular.module('gettext').factory('gettextCatalog', ["gettextPlurals", "$http", } }; + // Trim polyfill for old browsers (instead of jQuery) + // Based on AngularJS-v1.2.2 (angular.js#620) + var trim = (function () { + if (!String.prototype.trim) { + return function (value) { + return (typeof value === 'string') ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value; + }; + } + return function (value) { + return (typeof value === 'string') ? value.trim() : value; + }; + })(); + function broadcastUpdated() { $rootScope.$broadcast('gettextLanguageChanged'); } @@ -47,11 +60,17 @@ angular.module('gettext').factory('gettextCatalog', ["gettextPlurals", "$http", showTranslatedMarkers: false, translatedMarkerPrefix: '[', translatedMarkerSuffix: ']', + idTransform: function (s) { return trim(s); }, strings: {}, baseLanguage: 'en', currentLanguage: 'en', cache: $cacheFactory('strings'), + setIdTransform: function (idTransform) { + this.idTransform = idTransform; + broadcastUpdated(); + }, + setCurrentLanguage: function (lang) { this.currentLanguage = lang; broadcastUpdated(); @@ -93,8 +112,9 @@ angular.module('gettext').factory('gettextCatalog', ["gettextPlurals", "$http", }, getStringForm: function (string, n, context) { + var msgId = (typeof string === 'string') ? this.idTransform(string) : string; var stringTable = this.strings[this.currentLanguage] || {}; - var contexts = stringTable[string] || {}; + var contexts = stringTable[msgId] || {}; var plurals = contexts[context || noContext] || []; return plurals[n]; }, @@ -132,18 +152,6 @@ angular.module('gettext').factory('gettextCatalog', ["gettextPlurals", "$http", }]); angular.module('gettext').directive('translate', ["gettextCatalog", "$parse", "$animate", "$compile", "$window", function (gettextCatalog, $parse, $animate, $compile, $window) { - // Trim polyfill for old browsers (instead of jQuery) - // Based on AngularJS-v1.2.2 (angular.js#620) - var trim = (function () { - if (!String.prototype.trim) { - return function (value) { - return (typeof value === 'string') ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value; - }; - } - return function (value) { - return (typeof value === 'string') ? value.trim() : value; - }; - })(); function assert(condition, missing, found) { if (!condition) { @@ -161,7 +169,7 @@ angular.module('gettext').directive('translate', ["gettextCatalog", "$parse", "$ assert(!attrs.translatePlural || attrs.translateN, 'translate-n', 'translate-plural'); assert(!attrs.translateN || attrs.translatePlural, 'translate-plural', 'translate-n'); - var msgid = trim(element.html()); + var msgid = element.html(); var translatePlural = attrs.translatePlural; var translateContext = attrs.translateContext; diff --git a/dist/angular-gettext.min.js b/dist/angular-gettext.min.js index 07013fd..60948c5 100644 --- a/dist/angular-gettext.min.js +++ b/dist/angular-gettext.min.js @@ -1 +1 @@ -angular.module("gettext",[]),angular.module("gettext").constant("gettext",function(a){return a}),angular.module("gettext").factory("gettextCatalog",["gettextPlurals","$http","$cacheFactory","$interpolate","$rootScope",function(a,b,c,d,e){function f(){e.$broadcast("gettextLanguageChanged")}var g,h="$$noContext",i='test',j=angular.element(""+i+"").html()!==i,k=function(a){return g.debug&&g.currentLanguage!==g.baseLanguage?g.debugPrefix+a:a},l=function(a){return g.showTranslatedMarkers?g.translatedMarkerPrefix+a+g.translatedMarkerSuffix:a};return g={debug:!1,debugPrefix:"[MISSING]: ",showTranslatedMarkers:!1,translatedMarkerPrefix:"[",translatedMarkerSuffix:"]",strings:{},baseLanguage:"en",currentLanguage:"en",cache:c("strings"),setCurrentLanguage:function(a){this.currentLanguage=a,f()},getCurrentLanguage:function(){return this.currentLanguage},setStrings:function(a,b){this.strings[a]||(this.strings[a]={});for(var c in b){var d=b[c];if(j&&(c=angular.element(""+c+"").html()),angular.isString(d)||angular.isArray(d)){var e={};e[h]=d,d=e}for(var g in d){var i=d[g];d[g]=angular.isArray(i)?i:[i]}this.strings[a][c]=d}f()},getStringForm:function(a,b,c){var d=this.strings[this.currentLanguage]||{},e=d[a]||{},f=e[c||h]||[];return f[b]},getString:function(a,b,c){return a=this.getStringForm(a,0,c)||k(a),a=b?d(a)(b):a,l(a)},getPlural:function(b,c,e,f,g){var h=a(this.currentLanguage,b);return c=this.getStringForm(c,h,g)||k(1===b?c:e),f&&(f.$count=b,c=d(c)(f)),l(c)},loadRemote:function(a){return b({method:"GET",url:a,cache:g.cache}).success(function(a){for(var b in a)g.setStrings(b,a[b])})}}}]),angular.module("gettext").directive("translate",["gettextCatalog","$parse","$animate","$compile","$window",function(a,b,c,d,e){function f(a,b,c){if(!a)throw new Error("You should add a "+b+" attribute whenever you add a "+c+" attribute.")}var g=function(){return String.prototype.trim?function(a){return"string"==typeof a?a.trim():a}:function(a){return"string"==typeof a?a.replace(/^\s*/,"").replace(/\s*$/,""):a}}(),h=parseInt((/msie (\d+)/.exec(angular.lowercase(e.navigator.userAgent))||[])[1],10);return{restrict:"AE",terminal:!0,compile:function(e,i){f(!i.translatePlural||i.translateN,"translate-n","translate-plural"),f(!i.translateN||i.translatePlural,"translate-plural","translate-n");var j=g(e.html()),k=i.translatePlural,l=i.translateContext;return 8>=h&&""===j.slice(-13)&&(j=j.slice(0,-13)),{post:function(e,f,g){function h(){var b;k?(e=m||(m=e.$new()),e.$count=i(e),b=a.getPlural(e.$count,j,k,null,l)):b=a.getString(j,null,l);var g=angular.element(""+b+"");d(g.contents())(e);var h=f.contents(),n=g.contents();c.enter(n,f),c.leave(h)}var i=b(g.translateN),m=null;g.translateN&&e.$watch(g.translateN,h),e.$on("gettextLanguageChanged",h),h()}}}}}]),angular.module("gettext").filter("translate",["gettextCatalog",function(a){function b(b,c){return a.getString(b,null,c)}return b.$stateful=!0,b}]),angular.module("gettext").factory("gettextPlurals",function(){return function(a,b){switch(a){case"ay":case"bo":case"cgg":case"dz":case"fa":case"id":case"ja":case"jbo":case"ka":case"kk":case"km":case"ko":case"ky":case"lo":case"ms":case"my":case"sah":case"su":case"th":case"tt":case"ug":case"vi":case"wo":case"zh":return 0;case"is":return b%10!=1||b%100==11?1:0;case"jv":return 0!=b?1:0;case"mk":return 1==b||b%10==1?0:1;case"ach":case"ak":case"am":case"arn":case"br":case"fil":case"fr":case"gun":case"ln":case"mfe":case"mg":case"mi":case"oc":case"pt_BR":case"tg":case"ti":case"tr":case"uz":case"wa":case"zh":return b>1?1:0;case"lv":return b%10==1&&b%100!=11?0:0!=b?1:2;case"lt":return b%10==1&&b%100!=11?0:b%10>=2&&(10>b%100||b%100>=20)?1:2;case"be":case"bs":case"hr":case"ru":case"sr":case"uk":return b%10==1&&b%100!=11?0:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?1:2;case"mnk":return 0==b?0:1==b?1:2;case"ro":return 1==b?0:0==b||b%100>0&&20>b%100?1:2;case"pl":return 1==b?0:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?1:2;case"cs":case"sk":return 1==b?0:b>=2&&4>=b?1:2;case"sl":return b%100==1?1:b%100==2?2:b%100==3||b%100==4?3:0;case"mt":return 1==b?0:0==b||b%100>1&&11>b%100?1:b%100>10&&20>b%100?2:3;case"gd":return 1==b||11==b?0:2==b||12==b?1:b>2&&20>b?2:3;case"cy":return 1==b?0:2==b?1:8!=b&&11!=b?2:3;case"kw":return 1==b?0:2==b?1:3==b?2:3;case"ga":return 1==b?0:2==b?1:7>b?2:11>b?3:4;case"ar":return 0==b?0:1==b?1:2==b?2:b%100>=3&&10>=b%100?3:b%100>=11?4:5;default:return 1!=b?1:0}}}); \ No newline at end of file +angular.module("gettext",[]),angular.module("gettext").constant("gettext",function(a){return a}),angular.module("gettext").factory("gettextCatalog",["gettextPlurals","$http","$cacheFactory","$interpolate","$rootScope",function(a,b,c,d,e){function f(){e.$broadcast("gettextLanguageChanged")}var g,h="$$noContext",i='test',j=angular.element(""+i+"").html()!==i,k=function(a){return g.debug&&g.currentLanguage!==g.baseLanguage?g.debugPrefix+a:a},l=function(a){return g.showTranslatedMarkers?g.translatedMarkerPrefix+a+g.translatedMarkerSuffix:a},m=function(){return String.prototype.trim?function(a){return"string"==typeof a?a.trim():a}:function(a){return"string"==typeof a?a.replace(/^\s*/,"").replace(/\s*$/,""):a}}();return g={debug:!1,debugPrefix:"[MISSING]: ",showTranslatedMarkers:!1,translatedMarkerPrefix:"[",translatedMarkerSuffix:"]",idTransform:function(a){return m(a)},strings:{},baseLanguage:"en",currentLanguage:"en",cache:c("strings"),setIdTransform:function(a){this.idTransform=a,f()},setCurrentLanguage:function(a){this.currentLanguage=a,f()},getCurrentLanguage:function(){return this.currentLanguage},setStrings:function(a,b){this.strings[a]||(this.strings[a]={});for(var c in b){var d=b[c];if(j&&(c=angular.element(""+c+"").html()),angular.isString(d)||angular.isArray(d)){var e={};e[h]=d,d=e}for(var g in d){var i=d[g];d[g]=angular.isArray(i)?i:[i]}this.strings[a][c]=d}f()},getStringForm:function(a,b,c){var d="string"==typeof a?this.idTransform(a):a,e=this.strings[this.currentLanguage]||{},f=e[d]||{},g=f[c||h]||[];return g[b]},getString:function(a,b,c){return a=this.getStringForm(a,0,c)||k(a),a=b?d(a)(b):a,l(a)},getPlural:function(b,c,e,f,g){var h=a(this.currentLanguage,b);return c=this.getStringForm(c,h,g)||k(1===b?c:e),f&&(f.$count=b,c=d(c)(f)),l(c)},loadRemote:function(a){return b({method:"GET",url:a,cache:g.cache}).success(function(a){for(var b in a)g.setStrings(b,a[b])})}}}]),angular.module("gettext").directive("translate",["gettextCatalog","$parse","$animate","$compile","$window",function(a,b,c,d,e){function f(a,b,c){if(!a)throw new Error("You should add a "+b+" attribute whenever you add a "+c+" attribute.")}var g=parseInt((/msie (\d+)/.exec(angular.lowercase(e.navigator.userAgent))||[])[1],10);return{restrict:"AE",terminal:!0,compile:function(e,h){f(!h.translatePlural||h.translateN,"translate-n","translate-plural"),f(!h.translateN||h.translatePlural,"translate-plural","translate-n");var i=e.html(),j=h.translatePlural,k=h.translateContext;return 8>=g&&""===i.slice(-13)&&(i=i.slice(0,-13)),{post:function(e,f,g){function h(){var b;j?(e=m||(m=e.$new()),e.$count=l(e),b=a.getPlural(e.$count,i,j,null,k)):b=a.getString(i,null,k);var g=angular.element(""+b+"");d(g.contents())(e);var h=f.contents(),n=g.contents();c.enter(n,f),c.leave(h)}var l=b(g.translateN),m=null;g.translateN&&e.$watch(g.translateN,h),e.$on("gettextLanguageChanged",h),h()}}}}}]),angular.module("gettext").filter("translate",["gettextCatalog",function(a){function b(b,c){return a.getString(b,null,c)}return b.$stateful=!0,b}]),angular.module("gettext").factory("gettextPlurals",function(){return function(a,b){switch(a){case"ay":case"bo":case"cgg":case"dz":case"fa":case"id":case"ja":case"jbo":case"ka":case"kk":case"km":case"ko":case"ky":case"lo":case"ms":case"my":case"sah":case"su":case"th":case"tt":case"ug":case"vi":case"wo":case"zh":return 0;case"is":return b%10!=1||b%100==11?1:0;case"jv":return 0!=b?1:0;case"mk":return 1==b||b%10==1?0:1;case"ach":case"ak":case"am":case"arn":case"br":case"fil":case"fr":case"gun":case"ln":case"mfe":case"mg":case"mi":case"oc":case"pt_BR":case"tg":case"ti":case"tr":case"uz":case"wa":case"zh":return b>1?1:0;case"lv":return b%10==1&&b%100!=11?0:0!=b?1:2;case"lt":return b%10==1&&b%100!=11?0:b%10>=2&&(10>b%100||b%100>=20)?1:2;case"be":case"bs":case"hr":case"ru":case"sr":case"uk":return b%10==1&&b%100!=11?0:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?1:2;case"mnk":return 0==b?0:1==b?1:2;case"ro":return 1==b?0:0==b||b%100>0&&20>b%100?1:2;case"pl":return 1==b?0:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?1:2;case"cs":case"sk":return 1==b?0:b>=2&&4>=b?1:2;case"sl":return b%100==1?1:b%100==2?2:b%100==3||b%100==4?3:0;case"mt":return 1==b?0:0==b||b%100>1&&11>b%100?1:b%100>10&&20>b%100?2:3;case"gd":return 1==b||11==b?0:2==b||12==b?1:b>2&&20>b?2:3;case"cy":return 1==b?0:2==b?1:8!=b&&11!=b?2:3;case"kw":return 1==b?0:2==b?1:3==b?2:3;case"ga":return 1==b?0:2==b?1:7>b?2:11>b?3:4;case"ar":return 0==b?0:1==b?1:2==b?2:b%100>=3&&10>=b%100?3:b%100>=11?4:5;default:return 1!=b?1:0}}}); \ No newline at end of file diff --git a/src/catalog.js b/src/catalog.js index c6e776e..f4def0b 100644 --- a/src/catalog.js +++ b/src/catalog.js @@ -25,6 +25,19 @@ angular.module('gettext').factory('gettextCatalog', function (gettextPlurals, $h } }; + // Trim polyfill for old browsers (instead of jQuery) + // Based on AngularJS-v1.2.2 (angular.js#620) + var trim = (function () { + if (!String.prototype.trim) { + return function (value) { + return (typeof value === 'string') ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value; + }; + } + return function (value) { + return (typeof value === 'string') ? value.trim() : value; + }; + })(); + function broadcastUpdated() { $rootScope.$broadcast('gettextLanguageChanged'); } @@ -35,11 +48,17 @@ angular.module('gettext').factory('gettextCatalog', function (gettextPlurals, $h showTranslatedMarkers: false, translatedMarkerPrefix: '[', translatedMarkerSuffix: ']', + idTransform: function (s) { return trim(s); }, strings: {}, baseLanguage: 'en', currentLanguage: 'en', cache: $cacheFactory('strings'), + setIdTransform: function (idTransform) { + this.idTransform = idTransform; + broadcastUpdated(); + }, + setCurrentLanguage: function (lang) { this.currentLanguage = lang; broadcastUpdated(); @@ -81,8 +100,9 @@ angular.module('gettext').factory('gettextCatalog', function (gettextPlurals, $h }, getStringForm: function (string, n, context) { + var msgId = (typeof string === 'string') ? this.idTransform(string) : string; var stringTable = this.strings[this.currentLanguage] || {}; - var contexts = stringTable[string] || {}; + var contexts = stringTable[msgId] || {}; var plurals = contexts[context || noContext] || []; return plurals[n]; }, diff --git a/src/directive.js b/src/directive.js index 75409f1..fb41fd9 100644 --- a/src/directive.js +++ b/src/directive.js @@ -1,16 +1,4 @@ angular.module('gettext').directive('translate', function (gettextCatalog, $parse, $animate, $compile, $window) { - // Trim polyfill for old browsers (instead of jQuery) - // Based on AngularJS-v1.2.2 (angular.js#620) - var trim = (function () { - if (!String.prototype.trim) { - return function (value) { - return (typeof value === 'string') ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value; - }; - } - return function (value) { - return (typeof value === 'string') ? value.trim() : value; - }; - })(); function assert(condition, missing, found) { if (!condition) { @@ -28,7 +16,7 @@ angular.module('gettext').directive('translate', function (gettextCatalog, $pars assert(!attrs.translatePlural || attrs.translateN, 'translate-n', 'translate-plural'); assert(!attrs.translateN || attrs.translatePlural, 'translate-plural', 'translate-n'); - var msgid = trim(element.html()); + var msgid = element.html(); var translatePlural = attrs.translatePlural; var translateContext = attrs.translateContext; diff --git a/test/unit/directive.js b/test/unit/directive.js index 5b49b63..5eaca08 100644 --- a/test/unit/directive.js +++ b/test/unit/directive.js @@ -11,6 +11,7 @@ describe("Directive", function () { catalog = gettextCatalog; catalog.setStrings("nl", { Hello: "Hallo", + " Hello friend ": " Hallo amigo ", "Hello {{name}}!": "Hallo {{name}}!", "One boat": ["Een boot", "{{count}} boten"], Archive: { verb: "Archiveren", noun: "Archief" } @@ -26,6 +27,21 @@ describe("Directive", function () { assert.equal(el.text(), "Hello!"); }); + it("Should trim whitespace around the message id by default", function () { + catalog.setCurrentLanguage("nl"); + var el = $compile("

Hello

")($rootScope); + $rootScope.$digest(); + assert.equal(el.text(), "Hallo"); + }); + + it("Should let the message id transform be customized", function () { + catalog.setCurrentLanguage("nl"); + catalog.setIdTransform(function (s) { return s.replace(/\s+/g, " "); }); + var el = $compile("

Hello friend

")($rootScope); + $rootScope.$digest(); + assert.equal(el.text(), " Hallo amigo "); + }); + it("Should translate known strings", function () { catalog.setCurrentLanguage("nl"); var el = $compile("

Hello

")($rootScope);