diff --git a/dist/angular-gettext.js b/dist/angular-gettext.js
index b192bc8..5421130 100644
--- a/dist/angular-gettext.js
+++ b/dist/angular-gettext.js
@@ -10,8 +10,7 @@ angular.module('gettext').constant('gettext', function (str) {
return str;
});
-angular.module('gettext').factory('gettextCatalog', ["gettextPlurals", "$http", "$cacheFactory", "$interpolate", "$rootScope", function (gettextPlurals, $http, $cacheFactory, $interpolate, $rootScope) {
- var catalog;
+angular.module('gettext').provider('gettextCatalog', ["gettextPlurals", function (gettextPlurals) {
var noContext = '$$noContext';
// IE8 returns UPPER CASE tags, even though the source is lower case.
@@ -20,27 +19,7 @@ angular.module('gettext').factory('gettextCatalog', ["gettextPlurals", "$http",
var test = 'test';
var isUpperCaseTags = (angular.element('' + test + '').html() !== test);
- var prefixDebug = function (string) {
- if (catalog.debug && catalog.currentLanguage !== catalog.baseLanguage) {
- return catalog.debugPrefix + string;
- } else {
- return string;
- }
- };
-
- var addTranslatedMarkers = function (string) {
- if (catalog.showTranslatedMarkers) {
- return catalog.translatedMarkerPrefix + string + catalog.translatedMarkerSuffix;
- } else {
- return string;
- }
- };
-
- function broadcastUpdated() {
- $rootScope.$broadcast('gettextLanguageChanged');
- }
-
- catalog = {
+ var provider = {
debug: false,
debugPrefix: '[MISSING]: ',
showTranslatedMarkers: false,
@@ -49,11 +28,9 @@ angular.module('gettext').factory('gettextCatalog', ["gettextPlurals", "$http",
strings: {},
baseLanguage: 'en',
currentLanguage: 'en',
- cache: $cacheFactory('strings'),
setCurrentLanguage: function (lang) {
this.currentLanguage = lang;
- broadcastUpdated();
},
setStrings: function (language, strings) {
@@ -83,8 +60,6 @@ angular.module('gettext').factory('gettextCatalog', ["gettextPlurals", "$http",
}
this.strings[language][key] = val;
}
-
- broadcastUpdated();
},
getStringForm: function (string, n, context) {
@@ -92,38 +67,90 @@ angular.module('gettext').factory('gettextCatalog', ["gettextPlurals", "$http",
var contexts = stringTable[string] || {};
var plurals = contexts[context || noContext] || [];
return plurals[n];
- },
+ }
+ };
- getString: function (string, scope, context) {
- string = this.getStringForm(string, 0, context) || prefixDebug(string);
- string = scope ? $interpolate(string)(scope) : string;
- return addTranslatedMarkers(string);
- },
+ angular.extend(this, provider);
+
+ var self = this;
+ this.$get = /* @ngInject */ ["$injector", function ($injector) {
+ // lazily inject these to prevent circular dependecies
+ var $http;
+ var $interpolate;
+ var $rootScope;
+
+ function Catalog(options) {
+ angular.extend(this, options);
+ var self = this;
+
+ var prefixDebug = function (string) {
+ if (self.debug && self.currentLanguage !== self.baseLanguage) {
+ return self.debugPrefix + string;
+ } else {
+ return string;
+ }
+ };
- getPlural: function (n, string, stringPlural, scope, context) {
- var form = gettextPlurals(this.currentLanguage, n);
- string = this.getStringForm(string, form, context) || prefixDebug(n === 1 ? string : stringPlural);
- if (scope) {
- scope.$count = n;
- string = $interpolate(string)(scope);
+ var addTranslatedMarkers = function (string) {
+ if (self.showTranslatedMarkers) {
+ return self.translatedMarkerPrefix + string + self.translatedMarkerSuffix;
+ } else {
+ return string;
+ }
+ };
+
+ function broadcastUpdated() {
+ $rootScope = $rootScope || $injector.get('$rootScope');
+ $rootScope.$broadcast('gettextLanguageChanged');
}
- return addTranslatedMarkers(string);
- },
- loadRemote: function (url) {
- return $http({
- method: 'GET',
- url: url,
- cache: catalog.cache
- }).success(function (data) {
- for (var lang in data) {
- catalog.setStrings(lang, data[lang]);
+ this.setCurrentLanguage = function () {
+ options.setCurrentLanguage.apply(this, arguments);
+ broadcastUpdated();
+ };
+
+ this.setStrings = function () {
+ options.setStrings.apply(this, arguments);
+ broadcastUpdated();
+ };
+
+ this.getString = function (string, scope, context) {
+ $interpolate = $interpolate || $injector.get('$interpolate');
+
+ string = this.getStringForm(string, 0, context) || prefixDebug(string);
+ string = scope ? $interpolate(string)(scope) : string;
+ return addTranslatedMarkers(string);
+ };
+
+ this.getPlural = function (n, string, stringPlural, scope, context) {
+ $interpolate = $interpolate || $injector.get('$interpolate');
+
+ var form = gettextPlurals(this.currentLanguage, n);
+ string = this.getStringForm(string, form, context) || prefixDebug(n === 1 ? string : stringPlural);
+ if (scope) {
+ scope.$count = n;
+ string = $interpolate(string)(scope);
}
- });
+ return addTranslatedMarkers(string);
+ };
+
+ this.loadRemote = function (url) {
+ $http = $http || $injector.get('$http');
+ return $http({
+ method: 'GET',
+ url: url,
+ cache: self.cache
+ }).success(function (data) {
+ for (var lang in data) {
+ self.setStrings(lang, data[lang]);
+ }
+ });
+ };
}
- };
- return catalog;
+ self.cache = self.cache || $injector.get('$cacheFactory')('strings');
+ return new Catalog(self);
+ }];
}]);
angular.module('gettext').directive('translate', ["gettextCatalog", "$parse", "$animate", "$compile", "$window", function (gettextCatalog, $parse, $animate, $compile, $window) {
@@ -215,116 +242,117 @@ angular.module('gettext').filter('translate', ["gettextCatalog", function (gette
}]);
// Do not edit this file, it is autogenerated using genplurals.py!
-angular.module("gettext").factory("gettextPlurals", function () {
- return function (langCode, n) {
- switch (langCode) {
- case "ay": // Aymará
- case "bo": // Tibetan
- case "cgg": // Chiga
- case "dz": // Dzongkha
- case "fa": // Persian
- case "id": // Indonesian
- case "ja": // Japanese
- case "jbo": // Lojban
- case "ka": // Georgian
- case "kk": // Kazakh
- case "km": // Khmer
- case "ko": // Korean
- case "ky": // Kyrgyz
- case "lo": // Lao
- case "ms": // Malay
- case "my": // Burmese
- case "sah": // Yakut
- case "su": // Sundanese
- case "th": // Thai
- case "tt": // Tatar
- case "ug": // Uyghur
- case "vi": // Vietnamese
- case "wo": // Wolof
- case "zh": // Chinese
- // 1 form
- return 0;
- case "is": // Icelandic
- // 2 forms
- return (n%10!=1 || n%100==11) ? 1 : 0;
- case "jv": // Javanese
- // 2 forms
- return n!=0 ? 1 : 0;
- case "mk": // Macedonian
- // 2 forms
- return n==1 || n%10==1 ? 0 : 1;
- case "ach": // Acholi
- case "ak": // Akan
- case "am": // Amharic
- case "arn": // Mapudungun
- case "br": // Breton
- case "fil": // Filipino
- case "fr": // French
- case "gun": // Gun
- case "ln": // Lingala
- case "mfe": // Mauritian Creole
- case "mg": // Malagasy
- case "mi": // Maori
- case "oc": // Occitan
- case "pt_BR": // Brazilian Portuguese
- case "tg": // Tajik
- case "ti": // Tigrinya
- case "tr": // Turkish
- case "uz": // Uzbek
- case "wa": // Walloon
- case "zh": // Chinese
- // 2 forms
- return n>1 ? 1 : 0;
- case "lv": // Latvian
- // 3 forms
- return (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);
- case "lt": // Lithuanian
- // 3 forms
- return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);
- case "be": // Belarusian
- case "bs": // Bosnian
- case "hr": // Croatian
- case "ru": // Russian
- case "sr": // Serbian
- case "uk": // Ukrainian
- // 3 forms
- return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);
- case "mnk": // Mandinka
- // 3 forms
- return (n==0 ? 0 : n==1 ? 1 : 2);
- case "ro": // Romanian
- // 3 forms
- return (n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);
- case "pl": // Polish
- // 3 forms
- return (n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);
- case "cs": // Czech
- case "sk": // Slovak
- // 3 forms
- return (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;
- case "sl": // Slovenian
- // 4 forms
- return (n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);
- case "mt": // Maltese
- // 4 forms
- return (n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3);
- case "gd": // Scottish Gaelic
- // 4 forms
- return (n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;
- case "cy": // Welsh
- // 4 forms
- return (n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;
- case "kw": // Cornish
- // 4 forms
- return (n==1) ? 0 : (n==2) ? 1 : (n == 3) ? 2 : 3;
- case "ga": // Irish
- // 5 forms
- return n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4;
- case "ar": // Arabic
- // 6 forms
- return (n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5);
- default: // Everything else
- return n != 1 ? 1 : 0;
- }
+angular.module("gettext").constant("gettextPlurals", function (langCode, n) {
+ switch (langCode) {
+ case "ay": // Aymará
+ case "bo": // Tibetan
+ case "cgg": // Chiga
+ case "dz": // Dzongkha
+ case "fa": // Persian
+ case "id": // Indonesian
+ case "ja": // Japanese
+ case "jbo": // Lojban
+ case "ka": // Georgian
+ case "kk": // Kazakh
+ case "km": // Khmer
+ case "ko": // Korean
+ case "ky": // Kyrgyz
+ case "lo": // Lao
+ case "ms": // Malay
+ case "my": // Burmese
+ case "sah": // Yakut
+ case "su": // Sundanese
+ case "th": // Thai
+ case "tt": // Tatar
+ case "ug": // Uyghur
+ case "vi": // Vietnamese
+ case "wo": // Wolof
+ case "zh": // Chinese
+ // 1 form
+ return 0;
+ case "is": // Icelandic
+ // 2 forms
+ return (n%10!=1 || n%100==11) ? 1 : 0;
+ case "jv": // Javanese
+ // 2 forms
+ return n!=0 ? 1 : 0;
+ case "mk": // Macedonian
+ // 2 forms
+ return n==1 || n%10==1 ? 0 : 1;
+ case "ach": // Acholi
+ case "ak": // Akan
+ case "am": // Amharic
+ case "arn": // Mapudungun
+ case "br": // Breton
+ case "fil": // Filipino
+ case "fr": // French
+ case "gun": // Gun
+ case "ln": // Lingala
+ case "mfe": // Mauritian Creole
+ case "mg": // Malagasy
+ case "mi": // Maori
+ case "oc": // Occitan
+ case "pt_BR": // Brazilian Portuguese
+ case "tg": // Tajik
+ case "ti": // Tigrinya
+ case "tr": // Turkish
+ case "uz": // Uzbek
+ case "wa": // Walloon
+ case "zh": // Chinese
+ // 2 forms
+ return n>1 ? 1 : 0;
+ case "lv": // Latvian
+ // 3 forms
+ return (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);
+ case "lt": // Lithuanian
+ // 3 forms
+ return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);
+ case "be": // Belarusian
+ case "bs": // Bosnian
+ case "hr": // Croatian
+ case "ru": // Russian
+ case "sr": // Serbian
+ case "uk": // Ukrainian
+ // 3 forms
+ return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);
+ case "mnk": // Mandinka
+ // 3 forms
+ return (n==0 ? 0 : n==1 ? 1 : 2);
+ case "ro": // Romanian
+ // 3 forms
+ return (n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);
+ case "pl": // Polish
+ // 3 forms
+ return (n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);
+ case "cs": // Czech
+ case "sk": // Slovak
+ // 3 forms
+ return (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;
+ case "csb": // Kashubian
+ // 3 forms
+ return (n==1) ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
+ case "sl": // Slovenian
+ // 4 forms
+ return (n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);
+ case "mt": // Maltese
+ // 4 forms
+ return (n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3);
+ case "gd": // Scottish Gaelic
+ // 4 forms
+ return (n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;
+ case "cy": // Welsh
+ // 4 forms
+ return (n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;
+ case "kw": // Cornish
+ // 4 forms
+ return (n==1) ? 0 : (n==2) ? 1 : (n == 3) ? 2 : 3;
+ case "ga": // Irish
+ // 5 forms
+ return (n==1) ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4;
+ case "ar": // Arabic
+ // 6 forms
+ return (n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5);
+ default: // Everything else
+ return n != 1 ? 1 : 0;
}
});
diff --git a/dist/angular-gettext.min.js b/dist/angular-gettext.min.js
index a7cb823..aac6b57 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()},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").provider("gettextCatalog",["gettextPlurals",function(a){var b="$$noContext",c="test",d=angular.element(""+c+"").html()!==c,e={debug:!1,debugPrefix:"[MISSING]: ",showTranslatedMarkers:!1,translatedMarkerPrefix:"[",translatedMarkerSuffix:"]",strings:{},baseLanguage:"en",currentLanguage:"en",setCurrentLanguage:function(a){this.currentLanguage=a},setStrings:function(a,c){this.strings[a]||(this.strings[a]={});for(var e in c){var f=c[e];if(d&&(e=angular.element(""+e+"").html()),angular.isString(f)||angular.isArray(f)){var g={};g[b]=f,f=g}for(var h in f){var i=f[h];f[h]=angular.isArray(i)?i:[i]}this.strings[a][e]=f}},getStringForm:function(a,c,d){var e=this.strings[this.currentLanguage]||{},f=e[a]||{},g=f[d||b]||[];return g[c]}};angular.extend(this,e);var f=this;this.$get=["$injector",function(b){function c(c){function f(){g=g||b.get("$rootScope"),g.$broadcast("gettextLanguageChanged")}angular.extend(this,c);var h=this,i=function(a){return h.debug&&h.currentLanguage!==h.baseLanguage?h.debugPrefix+a:a},j=function(a){return h.showTranslatedMarkers?h.translatedMarkerPrefix+a+h.translatedMarkerSuffix:a};this.setCurrentLanguage=function(){c.setCurrentLanguage.apply(this,arguments),f()},this.setStrings=function(){c.setStrings.apply(this,arguments),f()},this.getString=function(a,c,d){return e=e||b.get("$interpolate"),a=this.getStringForm(a,0,d)||i(a),a=c?e(a)(c):a,j(a)},this.getPlural=function(c,d,f,g,h){e=e||b.get("$interpolate");var k=a(this.currentLanguage,c);return d=this.getStringForm(d,k,h)||i(1===c?d:f),g&&(g.$count=c,d=e(d)(g)),j(d)},this.loadRemote=function(a){return d=d||b.get("$http"),d({method:"GET",url:a,cache:h.cache}).success(function(a){for(var b in a)h.setStrings(b,a[b])})}}var d,e,g;return f.cache=f.cache||b.get("$cacheFactory")("strings"),new c(f)}]}]),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").constant("gettextPlurals",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"csb":return 1==b?0:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?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/genplurals.py b/genplurals.py
index c28e54e..1890a18 100755
--- a/genplurals.py
+++ b/genplurals.py
@@ -110,9 +110,8 @@ def handle_entityref(self, name):
rules.sort(key = lambda rule: (str(rule[1][0][2]) + rule[0]))
print('// Do not edit this file, it is autogenerated using genplurals.py!');
-print('angular.module("gettext").factory("gettextPlurals", function () {');
-print(' return function (langCode, n) {')
-print(' switch (langCode) {')
+print('angular.module("gettext").constant("gettextPlurals", function (langCode, n) {');
+print(' switch (langCode) {')
for rule, langs in rules:
last_forms = 0
langs.sort(key = lambda lang: lang[0])
@@ -121,14 +120,13 @@ def handle_entityref(self, name):
space = ' '
if len(code) == 3:
space = ' '
- print(' case "%s":%s// %s' % (code, space, name))
+ print(' case "%s":%s// %s' % (code, space, name))
if last_forms == 1:
- print(' // %d form' % last_forms)
+ print(' // %d form' % last_forms)
else:
- print(' // %d forms' % last_forms)
- print(' return %s;' % rule)
-print(' default: // Everything else')
-print(' return n != 1 ? 1 : 0;')
-print(' }')
+ print(' // %d forms' % last_forms)
+ print(' return %s;' % rule)
+print(' default: // Everything else')
+print(' return n != 1 ? 1 : 0;')
print(' }')
print('});')
diff --git a/src/catalog.js b/src/catalog.js
index 3782b36..36ea3a6 100644
--- a/src/catalog.js
+++ b/src/catalog.js
@@ -1,5 +1,4 @@
-angular.module('gettext').factory('gettextCatalog', function (gettextPlurals, $http, $cacheFactory, $interpolate, $rootScope) {
- var catalog;
+angular.module('gettext').provider('gettextCatalog', function (gettextPlurals) {
var noContext = '$$noContext';
// IE8 returns UPPER CASE tags, even though the source is lower case.
@@ -8,27 +7,7 @@ angular.module('gettext').factory('gettextCatalog', function (gettextPlurals, $h
var test = 'test';
var isUpperCaseTags = (angular.element('' + test + '').html() !== test);
- var prefixDebug = function (string) {
- if (catalog.debug && catalog.currentLanguage !== catalog.baseLanguage) {
- return catalog.debugPrefix + string;
- } else {
- return string;
- }
- };
-
- var addTranslatedMarkers = function (string) {
- if (catalog.showTranslatedMarkers) {
- return catalog.translatedMarkerPrefix + string + catalog.translatedMarkerSuffix;
- } else {
- return string;
- }
- };
-
- function broadcastUpdated() {
- $rootScope.$broadcast('gettextLanguageChanged');
- }
-
- catalog = {
+ var provider = {
debug: false,
debugPrefix: '[MISSING]: ',
showTranslatedMarkers: false,
@@ -37,11 +16,9 @@ angular.module('gettext').factory('gettextCatalog', function (gettextPlurals, $h
strings: {},
baseLanguage: 'en',
currentLanguage: 'en',
- cache: $cacheFactory('strings'),
setCurrentLanguage: function (lang) {
this.currentLanguage = lang;
- broadcastUpdated();
},
setStrings: function (language, strings) {
@@ -71,8 +48,6 @@ angular.module('gettext').factory('gettextCatalog', function (gettextPlurals, $h
}
this.strings[language][key] = val;
}
-
- broadcastUpdated();
},
getStringForm: function (string, n, context) {
@@ -80,36 +55,88 @@ angular.module('gettext').factory('gettextCatalog', function (gettextPlurals, $h
var contexts = stringTable[string] || {};
var plurals = contexts[context || noContext] || [];
return plurals[n];
- },
+ }
+ };
- getString: function (string, scope, context) {
- string = this.getStringForm(string, 0, context) || prefixDebug(string);
- string = scope ? $interpolate(string)(scope) : string;
- return addTranslatedMarkers(string);
- },
+ angular.extend(this, provider);
+
+ var self = this;
+ this.$get = /* @ngInject */ function ($injector) {
+ // lazily inject these to prevent circular dependecies
+ var $http;
+ var $interpolate;
+ var $rootScope;
- getPlural: function (n, string, stringPlural, scope, context) {
- var form = gettextPlurals(this.currentLanguage, n);
- string = this.getStringForm(string, form, context) || prefixDebug(n === 1 ? string : stringPlural);
- if (scope) {
- scope.$count = n;
- string = $interpolate(string)(scope);
+ function Catalog(options) {
+ angular.extend(this, options);
+ var self = this;
+
+ var prefixDebug = function (string) {
+ if (self.debug && self.currentLanguage !== self.baseLanguage) {
+ return self.debugPrefix + string;
+ } else {
+ return string;
+ }
+ };
+
+ var addTranslatedMarkers = function (string) {
+ if (self.showTranslatedMarkers) {
+ return self.translatedMarkerPrefix + string + self.translatedMarkerSuffix;
+ } else {
+ return string;
+ }
+ };
+
+ function broadcastUpdated() {
+ $rootScope = $rootScope || $injector.get('$rootScope');
+ $rootScope.$broadcast('gettextLanguageChanged');
}
- return addTranslatedMarkers(string);
- },
- loadRemote: function (url) {
- return $http({
- method: 'GET',
- url: url,
- cache: catalog.cache
- }).success(function (data) {
- for (var lang in data) {
- catalog.setStrings(lang, data[lang]);
+ this.setCurrentLanguage = function () {
+ options.setCurrentLanguage.apply(this, arguments);
+ broadcastUpdated();
+ };
+
+ this.setStrings = function () {
+ options.setStrings.apply(this, arguments);
+ broadcastUpdated();
+ };
+
+ this.getString = function (string, scope, context) {
+ $interpolate = $interpolate || $injector.get('$interpolate');
+
+ string = this.getStringForm(string, 0, context) || prefixDebug(string);
+ string = scope ? $interpolate(string)(scope) : string;
+ return addTranslatedMarkers(string);
+ };
+
+ this.getPlural = function (n, string, stringPlural, scope, context) {
+ $interpolate = $interpolate || $injector.get('$interpolate');
+
+ var form = gettextPlurals(this.currentLanguage, n);
+ string = this.getStringForm(string, form, context) || prefixDebug(n === 1 ? string : stringPlural);
+ if (scope) {
+ scope.$count = n;
+ string = $interpolate(string)(scope);
}
- });
+ return addTranslatedMarkers(string);
+ };
+
+ this.loadRemote = function (url) {
+ $http = $http || $injector.get('$http');
+ return $http({
+ method: 'GET',
+ url: url,
+ cache: self.cache
+ }).success(function (data) {
+ for (var lang in data) {
+ self.setStrings(lang, data[lang]);
+ }
+ });
+ };
}
- };
- return catalog;
+ self.cache = self.cache || $injector.get('$cacheFactory')('strings');
+ return new Catalog(self);
+ };
});
diff --git a/src/plural.js b/src/plural.js
index fc53d87..371e07f 100644
--- a/src/plural.js
+++ b/src/plural.js
@@ -1,114 +1,115 @@
// Do not edit this file, it is autogenerated using genplurals.py!
-angular.module("gettext").factory("gettextPlurals", function () {
- return function (langCode, n) {
- switch (langCode) {
- case "ay": // Aymará
- case "bo": // Tibetan
- case "cgg": // Chiga
- case "dz": // Dzongkha
- case "fa": // Persian
- case "id": // Indonesian
- case "ja": // Japanese
- case "jbo": // Lojban
- case "ka": // Georgian
- case "kk": // Kazakh
- case "km": // Khmer
- case "ko": // Korean
- case "ky": // Kyrgyz
- case "lo": // Lao
- case "ms": // Malay
- case "my": // Burmese
- case "sah": // Yakut
- case "su": // Sundanese
- case "th": // Thai
- case "tt": // Tatar
- case "ug": // Uyghur
- case "vi": // Vietnamese
- case "wo": // Wolof
- case "zh": // Chinese
- // 1 form
- return 0;
- case "is": // Icelandic
- // 2 forms
- return (n%10!=1 || n%100==11) ? 1 : 0;
- case "jv": // Javanese
- // 2 forms
- return n!=0 ? 1 : 0;
- case "mk": // Macedonian
- // 2 forms
- return n==1 || n%10==1 ? 0 : 1;
- case "ach": // Acholi
- case "ak": // Akan
- case "am": // Amharic
- case "arn": // Mapudungun
- case "br": // Breton
- case "fil": // Filipino
- case "fr": // French
- case "gun": // Gun
- case "ln": // Lingala
- case "mfe": // Mauritian Creole
- case "mg": // Malagasy
- case "mi": // Maori
- case "oc": // Occitan
- case "pt_BR": // Brazilian Portuguese
- case "tg": // Tajik
- case "ti": // Tigrinya
- case "tr": // Turkish
- case "uz": // Uzbek
- case "wa": // Walloon
- case "zh": // Chinese
- // 2 forms
- return n>1 ? 1 : 0;
- case "lv": // Latvian
- // 3 forms
- return (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);
- case "lt": // Lithuanian
- // 3 forms
- return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);
- case "be": // Belarusian
- case "bs": // Bosnian
- case "hr": // Croatian
- case "ru": // Russian
- case "sr": // Serbian
- case "uk": // Ukrainian
- // 3 forms
- return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);
- case "mnk": // Mandinka
- // 3 forms
- return (n==0 ? 0 : n==1 ? 1 : 2);
- case "ro": // Romanian
- // 3 forms
- return (n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);
- case "pl": // Polish
- // 3 forms
- return (n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);
- case "cs": // Czech
- case "sk": // Slovak
- // 3 forms
- return (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;
- case "sl": // Slovenian
- // 4 forms
- return (n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);
- case "mt": // Maltese
- // 4 forms
- return (n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3);
- case "gd": // Scottish Gaelic
- // 4 forms
- return (n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;
- case "cy": // Welsh
- // 4 forms
- return (n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;
- case "kw": // Cornish
- // 4 forms
- return (n==1) ? 0 : (n==2) ? 1 : (n == 3) ? 2 : 3;
- case "ga": // Irish
- // 5 forms
- return n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4;
- case "ar": // Arabic
- // 6 forms
- return (n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5);
- default: // Everything else
- return n != 1 ? 1 : 0;
- }
+angular.module("gettext").constant("gettextPlurals", function (langCode, n) {
+ switch (langCode) {
+ case "ay": // Aymará
+ case "bo": // Tibetan
+ case "cgg": // Chiga
+ case "dz": // Dzongkha
+ case "fa": // Persian
+ case "id": // Indonesian
+ case "ja": // Japanese
+ case "jbo": // Lojban
+ case "ka": // Georgian
+ case "kk": // Kazakh
+ case "km": // Khmer
+ case "ko": // Korean
+ case "ky": // Kyrgyz
+ case "lo": // Lao
+ case "ms": // Malay
+ case "my": // Burmese
+ case "sah": // Yakut
+ case "su": // Sundanese
+ case "th": // Thai
+ case "tt": // Tatar
+ case "ug": // Uyghur
+ case "vi": // Vietnamese
+ case "wo": // Wolof
+ case "zh": // Chinese
+ // 1 form
+ return 0;
+ case "is": // Icelandic
+ // 2 forms
+ return (n%10!=1 || n%100==11) ? 1 : 0;
+ case "jv": // Javanese
+ // 2 forms
+ return n!=0 ? 1 : 0;
+ case "mk": // Macedonian
+ // 2 forms
+ return n==1 || n%10==1 ? 0 : 1;
+ case "ach": // Acholi
+ case "ak": // Akan
+ case "am": // Amharic
+ case "arn": // Mapudungun
+ case "br": // Breton
+ case "fil": // Filipino
+ case "fr": // French
+ case "gun": // Gun
+ case "ln": // Lingala
+ case "mfe": // Mauritian Creole
+ case "mg": // Malagasy
+ case "mi": // Maori
+ case "oc": // Occitan
+ case "pt_BR": // Brazilian Portuguese
+ case "tg": // Tajik
+ case "ti": // Tigrinya
+ case "tr": // Turkish
+ case "uz": // Uzbek
+ case "wa": // Walloon
+ case "zh": // Chinese
+ // 2 forms
+ return n>1 ? 1 : 0;
+ case "lv": // Latvian
+ // 3 forms
+ return (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);
+ case "lt": // Lithuanian
+ // 3 forms
+ return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);
+ case "be": // Belarusian
+ case "bs": // Bosnian
+ case "hr": // Croatian
+ case "ru": // Russian
+ case "sr": // Serbian
+ case "uk": // Ukrainian
+ // 3 forms
+ return (n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);
+ case "mnk": // Mandinka
+ // 3 forms
+ return (n==0 ? 0 : n==1 ? 1 : 2);
+ case "ro": // Romanian
+ // 3 forms
+ return (n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);
+ case "pl": // Polish
+ // 3 forms
+ return (n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);
+ case "cs": // Czech
+ case "sk": // Slovak
+ // 3 forms
+ return (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;
+ case "csb": // Kashubian
+ // 3 forms
+ return (n==1) ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
+ case "sl": // Slovenian
+ // 4 forms
+ return (n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);
+ case "mt": // Maltese
+ // 4 forms
+ return (n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3);
+ case "gd": // Scottish Gaelic
+ // 4 forms
+ return (n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;
+ case "cy": // Welsh
+ // 4 forms
+ return (n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;
+ case "kw": // Cornish
+ // 4 forms
+ return (n==1) ? 0 : (n==2) ? 1 : (n == 3) ? 2 : 3;
+ case "ga": // Irish
+ // 5 forms
+ return (n==1) ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4;
+ case "ar": // Arabic
+ // 6 forms
+ return (n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5);
+ default: // Everything else
+ return n != 1 ? 1 : 0;
}
});
diff --git a/test/unit/circular.js b/test/unit/circular.js
new file mode 100644
index 0000000..c6ffb8d
--- /dev/null
+++ b/test/unit/circular.js
@@ -0,0 +1,20 @@
+describe("Catalog", function () {
+ // don't pull module out of tests!
+
+ it("Shouldn't cause circular dependency error on $http", function () {
+ var testModule = angular.module("gettext.test", function () {});
+ testModule.factory("testInterceptor", function (gettextCatalog) {
+ gettextCatalog.getString("some message");
+ return {};
+ });
+
+ testModule.config(function ($httpProvider) {
+ $httpProvider.interceptors.push("testInterceptor");
+ });
+
+ module("gettext", "gettext.test");
+ inject(function ($http) {
+ assert.notEqual($http, false);
+ });
+ });
+});
diff --git a/test/unit/gettextCatalogProvider.js b/test/unit/gettextCatalogProvider.js
new file mode 100644
index 0000000..01e71b6
--- /dev/null
+++ b/test/unit/gettextCatalogProvider.js
@@ -0,0 +1,45 @@
+describe('gettextCatalogProvider', function () {
+ var catalogProvider;
+ var $injector;
+
+ beforeEach(function () {
+ var testModule = angular.module('gettext.test', function () {});
+ testModule.config(function (gettextCatalogProvider) {
+ catalogProvider = gettextCatalogProvider;
+ });
+
+ module('gettext', 'gettext.test');
+ inject(function (_$injector_) {
+ $injector = _$injector_;
+ });
+ });
+
+ it('Can set strings', function () {
+ var strings = { Hello: 'Hallo' };
+ assert.deepEqual(catalogProvider.strings, {});
+ catalogProvider.setStrings('nl', strings);
+ assert.equal(catalogProvider.strings.nl.Hello.$$noContext[0], 'Hallo');
+
+ var catalog = $injector.invoke(catalogProvider.$get);
+ assert.equal(catalog.strings.nl.Hello.$$noContext[0], 'Hallo');
+ });
+
+ it('Should allow setting debug', function () {
+ assert.equal(catalogProvider.debug, false);
+ catalogProvider.debug = true;
+ catalogProvider.currentLanguage = 'fr';
+
+ var catalog = $injector.invoke(catalogProvider.$get);
+ assert.equal(catalog.getString('Hello'), '[MISSING]: Hello');
+ });
+
+ it('Should allow calling setCurrentLanguage', function () {
+ assert.equal(catalogProvider.currentLanguage, 'en');
+ catalogProvider.setCurrentLanguage('fr');
+ assert.equal(catalogProvider.currentLanguage, 'fr');
+
+ var catalog = $injector.invoke(catalogProvider.$get);
+ assert.equal(catalog.currentLanguage, 'fr');
+ });
+
+});