code: function (key) {
          if (!key) {
            throw 'No language key specified for loading.';
          }
  
          var deferred = $q.defer();
  
          $rootScope.$emit('$translateLoadingStart', {language: key});
          pendingLoader = true;
  
          var cache = loaderCache;
          if (typeof(cache) === 'string') {
            // getting on-demand instance of loader
            cache = $injector.get(cache);
          }
  
          var loaderOptions = angular.extend({}, $loaderOptions, {
            key: key,
            $http: angular.extend({}, {
              cache: cache
            }, $loaderOptions.$http)
          });
  
          $injector.get($loaderFactory)(loaderOptions).then(function (data) {
            var translationTable = {};
            $rootScope.$emit('$translateLoadingSuccess', {language: key});
  
            if (angular.isArray(data)) {
              angular.forEach(data, function (table) {
                angular.extend(translationTable, flatObject(table));
              });
            } else {
              angular.extend(translationTable, flatObject(data));
            }
            pendingLoader = false;
            deferred.resolve({
              key: key,
              table: translationTable
            });
            $rootScope.$emit('$translateLoadingEnd', {language: key});
          }, function (key) {
            $rootScope.$emit('$translateLoadingError', {language: key});
            deferred.reject(key);
            $rootScope.$emit('$translateLoadingEnd', {language: key});
          });
          return deferred.promise;
        }
docs: @name loadAsync
  @private
  
  @description
  Kicks of registered async loader using `$injector` and applies existing
  loader options. When resolved, it updates translation tables accordingly
  or rejects with given language key.
  
  @param {string} key Language key.
  @return {Promise} A promise.