text: /*!
   * angular-translate - v2.10.0 - 2016-02-28
   * 
   * Copyright (c) 2016 The angular-translate team, Pascal Precht; Licensed MIT
   */
  (function (root, factory) {
    if (typeof define === 'function' && define.amd) {
      // AMD. Register as an anonymous module unless amdModuleId is set
      define([], function () {
        return (factory());
      });
    } else if (typeof exports === 'object') {
      // Node. Does not work with strict CommonJS, but
      // only CommonJS-like environments that support module.exports,
      // like Node.
      module.exports = factory();
    } else {
      factory();
    }
  }(this, function () {
  
  angular.module('pascalprecht.translate')
  /**
   * @ngdoc object
   * @name pascalprecht.translate.$translatePartialLoaderProvider
   *
   * @description
   * By using a $translatePartialLoaderProvider you can configure a list of a needed
   * translation parts directly during the configuration phase of your application's
   * lifetime. All parts you add by using this provider would be loaded by
   * angular-translate at the startup as soon as possible.
   */
    .provider('$translatePartialLoader', $translatePartialLoader);
  
  function $translatePartialLoader() {
  
    'use strict';
  
    /**
     * @constructor
     * @name Part
     *
     * @description
     * Represents Part object to add and set parts at runtime.
     */
    function Part(name, priority) {
      this.name = name;
      this.isActive = true;
      this.tables = {};
      this.priority = priority || 0;
    }
  
    /**
     * @name parseUrl
     * @method
     *
     * @description
     * Returns a parsed url template string and replaces given target lang
     * and part name it.
     *
     * @param {string|function} urlTemplate - Either a string containing an url pattern (with
     *                                        '{part}' and '{lang}') or a function(part, lang)
     *                                        returning a string.
     * @param {string} targetLang - Language key for language to be used.
     * @return {string} Parsed url template string
     */
    Part.prototype.parseUrl = function(urlTemplate, targetLang) {
      if (angular.isFunction(urlTemplate)) {
        return urlTemplate(this.name, targetLang);
      }
      return urlTemplate.replace(/\{part\}/g, this.name).replace(/\{lang\}/g, targetLang);
    };
  
    Part.prototype.getTable = function(lang, $q, $http, $httpOptions, urlTemplate, errorHandler) {
  
      if (!this.tables[lang]) {
        var self = this;
  
        return $http(angular.extend({
          method : 'GET',
          url: this.parseUrl(urlTemplate, lang)
        }, $httpOptions))
          .then(function(result){
            self.tables[lang] = result.data;
            return result.data;
          }, function() {
            if (errorHandler) {
              return errorHandler(self.name, lang)
                .then(function(data) {
                  self.tables[lang] = data;
                  return data;
                }, function() {
                  return $q.reject(self.name);
                });
            } else {
              return $q.reject(self.name);
            }
          });
  
      } else {
        return $q.when(this.tables[lang]);
      }
    };
  
    var parts = {};
  
    function hasPart(name) {
      return Object.prototype.hasOwnProperty.call(parts, name);
    }
  
    function isStringValid(str) {
      return angular.isString(str) && str !== '';
    }
  
    function isPartAvailable(name) {
      if (!isStringValid(name)) {
        throw new TypeError('Invalid type of a first argument, a non-empty string expected.');
      }
  
      return (hasPart(name) && parts[name].isActive);
    }
  
    function deepExtend(dst, src) {
      for (var property in src) {
        if (src[property] && src[property].constructor &&
         src[property].constructor === Object) {
          dst[property] = dst[property] || {};
          deepExtend(dst[property], src[property]);
        } else {
          dst[property] = src[property];
        }
      }
      return dst;
    }
  
    function getPrioritizedParts() {
      var prioritizedParts = [];
      for(var part in parts) {
        if (parts[part].isActive) {
          prioritizedParts.push(parts[part]);
        }
      }
      prioritizedParts.sort(function (a, b) {
        return a.priority - b.priority;
      });
      return prioritizedParts;
    }
  
  
    /**
     * @ngdoc function
     * @name pascalprecht.translate.$translatePartialLoaderProvider#addPart
     * @methodOf pascalprecht.translate.$translatePartialLoaderProvider
     *
     * @description
     * Registers a new part of the translation table to be loaded once the
     * `angular-translate` gets into runtime phase. It does not actually load any
     * translation data, but only registers a part to be loaded in the future.
     *
     * @param {string} name A name of the part to add
     * @param {int} [priority=0] Sets the load priority of this part.
     *
     * @returns {object} $translatePartialLoaderProvider, so this method is chainable
     * @throws {TypeError} The method could throw a **TypeError** if you pass the param
     * of the wrong type. Please, note that the `name` param has to be a
     * non-empty **string**.
     */
    this.addPart = function(name, priority) {
      if (!isStringValid(name)) {
        throw new TypeError('Couldn\'t add part, part name has to be a string!');
      }
  
      if (!hasPart(name)) {
        parts[name] = new Part(name, priority);
      }
      parts[name].isActive = true;
  
      return this;
    };
  
    /**
     * @ngdocs function
     * @name pascalprecht.translate.$translatePartialLoaderProvider#setPart
     * @methodOf pascalprecht.translate.$translatePartialLoaderProvider
     *
     * @description
     * Sets a translation table to the specified part. This method does not make the
     * specified part available, but only avoids loading this part from the server.
     *
     * @param {string} lang A language of the given translation table
     * @param {string} part A name of the target part
     * @param {object} table A translation table to set to the specified part
     *
     * @return {object} $translatePartialLoaderProvider, so this method is chainable
     * @throws {TypeError} The method could throw a **TypeError** if you pass params
     * of the wrong type. Please, note that the `lang` and `part` params have to be a
     * non-empty **string**s and the `table` param has to be an object.
     */
    this.setPart = function (lang, part, table) {
      if (!isStringValid(lang)) {
        throw new TypeError('Couldn\'t set part.`lang` parameter has to be a string!');
      }
      if (!isStringValid(part)) {
        throw new TypeError('Couldn\'t set part.`part` parameter has to be a string!');
      }
      if (typeof table !== 'object' || table === null) {
        throw new TypeError('Couldn\'t set part. `table` parameter has to be an object!');
      }
  
      if (!hasPart(part)) {
        parts[part] = new Part(part);
        parts[part].isActive = false;
      }
  
      parts[part].tables[lang] = table;
      return this;
    };
  
    /**
     * @ngdoc function
     * @name pascalprecht.translate.$translatePartialLoaderProvider#deletePart
     * @methodOf pascalprecht.translate.$translatePartialLoaderProvider
     *
     * @description
     * Removes the previously added part of the translation data. So, `angular-translate` will not
     * load it at the startup.
     *
     * @param {string} name A name of the part to delete
     *
     * @returns {object} $translatePartialLoaderProvider, so this method is chainable
     *
     * @throws {TypeError} The method could throw a **TypeError** if you pass the param of the wrong
     * type. Please, note that the `name` param has to be a non-empty **string**.
     */
    this.deletePart = function (name) {
      if (!isStringValid(name)) {
        throw new TypeError('Couldn\'t delete part, first arg has to be string.');
      }
  
      if (hasPart(name)) {
        parts[name].isActive = false;
      }
  
      return this;
    };
  
  
    /**
     * @ngdoc function
     * @name pascalprecht.translate.$translatePartialLoaderProvider#isPartAvailable
     * @methodOf pascalprecht.translate.$translatePartialLoaderProvider
     *
     * @description
     * Checks if the specific part is available. A part becomes available after it was added by the
     * `addPart` method. Available parts would be loaded from the server once the `angular-translate`
     * asks the loader to that.
     *
     * @param {string} name A name of the part to check
     *
     * @returns {boolean} Returns **true** if the part is available now and **false** if not.
     *
     * @throws {TypeError} The method could throw a **TypeError** if you pass the param of the wrong
     * type. Please, note that the `name` param has to be a non-empty **string**.
     */
    this.isPartAvailable = isPartAvailable;
  
    /**
     * @ngdoc object
     * @name pascalprecht.translate.$translatePartialLoader
     *
     * @requires $q
     * @requires $http
     * @requires $injector
     * @requires $rootScope
     * @requires $translate
     *
     * @description
     *
     * @param {object} options Options object
     *
     * @throws {TypeError}
     */
    this.$get = ['$rootScope', '$injector', '$q', '$http',
    function($rootScope, $injector, $q, $http) {
  
      /**
       * @ngdoc event
       * @name pascalprecht.translate.$translatePartialLoader#$translatePartialLoaderStructureChanged
       * @eventOf pascalprecht.translate.$translatePartialLoader
       * @eventType broadcast on root scope
       *
       * @description
       * A $translatePartialLoaderStructureChanged event is called when a state of the loader was
       * changed somehow. It could mean either some part is added or some part is deleted. Anyway when
       * you get this event the translation table is not longer current and has to be updated.
       *
       * @param {string} name A name of the part which is a reason why the event was fired
       */
  
      var service = function(options) {
        if (!isStringValid(options.key)) {
          throw new TypeError('Unable to load data, a key is not a non-empty string.');
        }
  
        if (!isStringValid(options.urlTemplate) && !angular.isFunction(options.urlTemplate)) {
          throw new TypeError('Unable to load data, a urlTemplate is not a non-empty string or not a function.');
        }
  
        var errorHandler = options.loadFailureHandler;
        if (errorHandler !== undefined) {
          if (!angular.isString(errorHandler)) {
            throw new Error('Unable to load data, a loadFailureHandler is not a string.');
          } else {
            errorHandler = $injector.get(errorHandler);
          }
        }
  
        var loaders = [],
            prioritizedParts = getPrioritizedParts();
  
        angular.forEach(prioritizedParts, function(part) {
          loaders.push(
            part.getTable(options.key, $q, $http, options.$http, options.urlTemplate, errorHandler)
          );
          part.urlTemplate = options.urlTemplate;
        });
  
        return $q.all(loaders)
          .then(function() {
            var table = {};
            prioritizedParts = getPrioritizedParts();
            angular.forEach(prioritizedParts, function(part) {
              deepExtend(table, part.tables[options.key]);
            });
            return table;
          }, function() {
            return $q.reject(options.key);
          });
      };
  
      /**
       * @ngdoc function
       * @name pascalprecht.translate.$translatePartialLoader#addPart
       * @methodOf pascalprecht.translate.$translatePartialLoader
       *
       * @description
       * Registers a new part of the translation table. This method does not actually perform any xhr
       * requests to get translation data. The new parts will be loaded in order of priority from the server next time
       * `angular-translate` asks the loader to load translations.
       *
       * @param {string} name A name of the part to add
       * @param {int} [priority=0] Sets the load priority of this part.
       *
       * @returns {object} $translatePartialLoader, so this method is chainable
       *
       * @fires {$translatePartialLoaderStructureChanged} The $translatePartialLoaderStructureChanged
       * event would be fired by this method in case the new part affected somehow on the loaders
       * state. This way it means that there are a new translation data available to be loaded from
       * the server.
       *
       * @throws {TypeError} The method could throw a **TypeError** if you pass the param of the wrong
       * type. Please, note that the `name` param has to be a non-empty **string**.
       */
      service.addPart = function(name, priority) {
        if (!isStringValid(name)) {
          throw new TypeError('Couldn\'t add part, first arg has to be a string');
        }
  
        if (!hasPart(name)) {
          parts[name] = new Part(name, priority);
          $rootScope.$emit('$translatePartialLoaderStructureChanged', name);
        } else if (!parts[name].isActive) {
          parts[name].isActive = true;
          $rootScope.$emit('$translatePartialLoaderStructureChanged', name);
        }
  
        return service;
      };
  
      /**
       * @ngdoc function
       * @name pascalprecht.translate.$translatePartialLoader#deletePart
       * @methodOf pascalprecht.translate.$translatePartialLoader
       *
       * @description
       * Deletes the previously added part of the translation data. The target part could be deleted
       * either logically or physically. When the data is deleted logically it is not actually deleted
       * from the browser, but the loader marks it as not active and prevents it from affecting on the
       * translations. If the deleted in such way part is added again, the loader will use the
       * previously loaded data rather than loading it from the server once more time. But if the data
       * is deleted physically, the loader will completely remove all information about it. So in case
       * of recycling this part will be loaded from the server again.
       *
       * @param {string} name A name of the part to delete
       * @param {boolean=} [removeData=false] An indicator if the loader has to remove a loaded
       * translation data physically. If the `removeData` if set to **false** the loaded data will not be
       * deleted physically and might be reused in the future to prevent an additional xhr requests.
       *
       * @returns {object} $translatePartialLoader, so this method is chainable
       *
       * @fires {$translatePartialLoaderStructureChanged} The $translatePartialLoaderStructureChanged
       * event would be fired by this method in case a part deletion process affects somehow on the
       * loaders state. This way it means that some part of the translation data is now deprecated and
       * the translation table has to be recompiled with the remaining translation parts.
       *
       * @throws {TypeError} The method could throw a **TypeError** if you pass some param of the
       * wrong type. Please, note that the `name` param has to be a non-empty **string** and
       * the `removeData` param has to be either **undefined** or **boolean**.
       */
      service.deletePart = function(name, removeData) {
        if (!isStringValid(name)) {
          throw new TypeError('Couldn\'t delete part, first arg has to be string');
        }
  
        if (removeData === undefined) {
          removeData = false;
        } else if (typeof removeData !== 'boolean') {
          throw new TypeError('Invalid type of a second argument, a boolean expected.');
        }
  
        if (hasPart(name)) {
          var wasActive = parts[name].isActive;
          if (removeData) {
            var $translate = $injector.get('$translate');
            var cache = $translate.loaderCache();
            if (typeof(cache) === 'string') {
              // getting on-demand instance of loader
              cache = $injector.get(cache);
            }
            // Purging items from cache...
            if (typeof(cache) === 'object') {
              angular.forEach(parts[name].tables, function(value, key) {
                  cache.remove(parts[name].parseUrl(parts[name].urlTemplate, key));
              });
            }
            delete parts[name];
          } else {
            parts[name].isActive = false;
          }
          if (wasActive) {
            $rootScope.$emit('$translatePartialLoaderStructureChanged', name);
          }
        }
  
        return service;
      };
  
      /**
       * @ngdoc function
       * @name pascalprecht.translate.$translatePartialLoader#isPartLoaded
       * @methodOf pascalprecht.translate.$translatePartialLoader
       *
       * @description
       * Checks if the registered translation part is loaded into the translation table.
       *
       * @param {string} name A name of the part
       * @param {string} lang A key of the language
       *
       * @returns {boolean} Returns **true** if the translation of the part is loaded to the translation table and **false** if not.
       *
       * @throws {TypeError} The method could throw a **TypeError** if you pass the param of the wrong
       * type. Please, note that the `name` and `lang` params have to be non-empty **string**.
       */
      service.isPartLoaded = function(name, lang) {
        return angular.isDefined(parts[name]) && angular.isDefined(parts[name].tables[lang]);
      };
  
      /**
       * @ngdoc function
       * @name pascalprecht.translate.$translatePartialLoader#getRegisteredParts
       * @methodOf pascalprecht.translate.$translatePartialLoader
       *
       * @description
       * Gets names of the parts that were added with the `addPart`.
       *
       * @returns {array} Returns array of registered parts, if none were registered then an empty array is returned.
       */
      service.getRegisteredParts = function() {
        var registeredParts = [];
        angular.forEach(parts, function(p){
          if(p.isActive) {
            registeredParts.push(p.name);
          }
        });
        return registeredParts;
      };
  
  
  
      /**
       * @ngdoc function
       * @name pascalprecht.translate.$translatePartialLoader#isPartAvailable
       * @methodOf pascalprecht.translate.$translatePartialLoader
       *
       * @description
       * Checks if a target translation part is available. The part becomes available just after it was
       * added by the `addPart` method. Part's availability does not mean that it was loaded from the
       * server, but only that it was added to the loader. The available part might be loaded next
       * time the loader is called.
       *
       * @param {string} name A name of the part to delete
       *
       * @returns {boolean} Returns **true** if the part is available now and **false** if not.
       *
       * @throws {TypeError} The method could throw a **TypeError** if you pass the param of the wrong
       * type. Please, note that the `name` param has to be a non-empty **string**.
       */
      service.isPartAvailable = isPartAvailable;
  
      return service;
  
    }];
  
  }
  
  $translatePartialLoader.displayName = '$translatePartialLoader';
  return 'pascalprecht.translate';
  
  }));
  