from gitlab

This commit is contained in:
Jörg Henke
2023-12-04 11:52:12 +01:00
parent 05fa4e7209
commit 5fd979c3a4
585 changed files with 400301 additions and 0 deletions

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-2017 The angular-translate team and Pascal Precht
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,50 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 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 module === 'object' && module.exports) {
// 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 () {
$translateMissingTranslationHandlerLog.$inject = ['$log'];
angular.module('pascalprecht.translate')
/**
* @ngdoc object
* @name pascalprecht.translate.$translateMissingTranslationHandlerLog
* @requires $log
*
* @description
* Uses angular's `$log` service to give a warning when trying to translate a
* translation id which doesn't exist.
*
* @returns {function} Handler function
*/
.factory('$translateMissingTranslationHandlerLog', $translateMissingTranslationHandlerLog);
function $translateMissingTranslationHandlerLog ($log) {
'use strict';
return function (translationId) {
$log.warn('Translation for ' + translationId + ' doesn\'t exist');
};
}
$translateMissingTranslationHandlerLog.displayName = '$translateMissingTranslationHandlerLog';
return 'pascalprecht.translate';
}));

View File

@ -0,0 +1,6 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 The angular-translate team, Pascal Precht; Licensed MIT
*/
!function(n,t){"function"==typeof define&&define.amd?define([],function(){return t()}):"object"==typeof module&&module.exports?module.exports=t():t()}(0,function(){function n(t){"use strict";return function(n){t.warn("Translation for "+n+" doesn't exist")}}return n.$inject=["$log"],angular.module("pascalprecht.translate").factory("$translateMissingTranslationHandlerLog",n),n.displayName="$translateMissingTranslationHandlerLog","pascalprecht.translate"});

View File

@ -0,0 +1,197 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 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(["messageformat"], function (a0) {
return (factory(a0));
});
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require("messageformat"));
} else {
factory(root["MessageFormat"]);
}
}(this, function (MessageFormat) {
angular.module('pascalprecht.translate')
/**
* @ngdoc property
* @name pascalprecht.translate.TRANSLATE_MF_INTERPOLATION_CACHE
* @requires TRANSLATE_MF_INTERPOLATION_CACHE
*
* @description
* Uses MessageFormat.js to interpolate strings against some values.
*/
.constant('TRANSLATE_MF_INTERPOLATION_CACHE', '$translateMessageFormatInterpolation')
/**
* @ngdoc object
* @name pascalprecht.translate.$translateMessageFormatInterpolationProvider
*
* @description
* Configurations for $translateMessageFormatInterpolation
*/
.provider('$translateMessageFormatInterpolation', $translateMessageFormatInterpolationProvider);
function $translateMessageFormatInterpolationProvider() {
'use strict';
var configurer;
/**
* @ngdoc function
* @name pascalprecht.translate.$translateMessageFormatInterpolationProvider#messageFormatConfigurer
* @methodOf pascalprecht.translate.$translateMessageFormatInterpolationProvider
*
* @description
* Defines an optional configurer for the MessageFormat instance.
*
* Note: This hook will be called whenever a new instance of MessageFormat will be created.
*
* @param {function} fn callback with the instance as argument
*/
this.messageFormatConfigurer = function (fn) {
configurer = fn;
};
/**
* @ngdoc object
* @name pascalprecht.translate.$translateMessageFormatInterpolation
* @requires pascalprecht.translate.TRANSLATE_MF_INTERPOLATION_CACHE
*
* @description
* Uses MessageFormat.js to interpolate strings against some values.
*
* Be aware to configure a proper sanitization strategy.
*
* See also:
* * {@link pascalprecht.translate.$translateSanitization}
* * {@link https://github.com/SlexAxton/messageformat.js}
*
* @return {object} $translateMessageFormatInterpolation Interpolator service
*/
this.$get = ['$translateSanitization', '$cacheFactory', 'TRANSLATE_MF_INTERPOLATION_CACHE', function ($translateSanitization, $cacheFactory, TRANSLATE_MF_INTERPOLATION_CACHE) {
return $translateMessageFormatInterpolation($translateSanitization, $cacheFactory, TRANSLATE_MF_INTERPOLATION_CACHE, configurer);
}];
}
function $translateMessageFormatInterpolation($translateSanitization, $cacheFactory, TRANSLATE_MF_INTERPOLATION_CACHE, messageFormatConfigurer) {
'use strict';
var $translateInterpolator = {},
$cache = $cacheFactory.get(TRANSLATE_MF_INTERPOLATION_CACHE),
// instantiate with default locale (which is 'en')
$mf = new MessageFormat('en'),
$identifier = 'messageformat';
if (angular.isFunction(messageFormatConfigurer)) {
messageFormatConfigurer($mf);
}
if (!$cache) {
// create cache if it doesn't exist already
$cache = $cacheFactory(TRANSLATE_MF_INTERPOLATION_CACHE);
}
$cache.put('en', $mf);
/**
* @ngdoc function
* @name pascalprecht.translate.$translateMessageFormatInterpolation#setLocale
* @methodOf pascalprecht.translate.$translateMessageFormatInterpolation
*
* @description
* Sets current locale (this is currently not use in this interpolation).
*
* @param {string} locale Language key or locale.
*/
$translateInterpolator.setLocale = function (locale) {
$mf = $cache.get(locale);
if (!$mf) {
$mf = new MessageFormat(locale);
if (angular.isFunction(messageFormatConfigurer)) {
messageFormatConfigurer($mf);
}
$cache.put(locale, $mf);
}
};
/**
* @ngdoc function
* @name pascalprecht.translate.$translateMessageFormatInterpolation#getInterpolationIdentifier
* @methodOf pascalprecht.translate.$translateMessageFormatInterpolation
*
* @description
* Returns an identifier for this interpolation service.
*
* @returns {string} $identifier
*/
$translateInterpolator.getInterpolationIdentifier = function () {
return $identifier;
};
/**
* @deprecated will be removed in 3.0
* @see {@link pascalprecht.translate.$translateSanitization}
*/
$translateInterpolator.useSanitizeValueStrategy = function (value) {
$translateSanitization.useStrategy(value);
return this;
};
/**
* @ngdoc function
* @name pascalprecht.translate.$translateMessageFormatInterpolation#interpolate
* @methodOf pascalprecht.translate.$translateMessageFormatInterpolation
*
* @description
* Interpolates given string against given interpolate params using MessageFormat.js.
*
* @returns {string} interpolated string.
*/
$translateInterpolator.interpolate = function (string, interpolationParams, context, sanitizeStrategy) {
interpolationParams = interpolationParams || {};
interpolationParams = $translateSanitization.sanitize(interpolationParams, 'params', sanitizeStrategy);
var compiledFunction = $cache.get('mf:' + string);
// if given string wasn't compiled yet, we do so now and never have to do it again
if (!compiledFunction) {
// Ensure explicit type if possible
// MessageFormat checks the actual type (i.e. for amount based conditions)
for (var key in interpolationParams) {
if (interpolationParams.hasOwnProperty(key)) {
// ensure number
var number = parseInt(interpolationParams[key], 10);
if (angular.isNumber(number) && ('' + number) === interpolationParams[key]) {
interpolationParams[key] = number;
}
}
}
compiledFunction = $mf.compile(string);
$cache.put('mf:' + string, compiledFunction);
}
var interpolatedText = compiledFunction(interpolationParams);
return $translateSanitization.sanitize(interpolatedText, 'text', sanitizeStrategy);
};
return $translateInterpolator;
}
$translateMessageFormatInterpolation.displayName = '$translateMessageFormatInterpolation';
return 'pascalprecht.translate';
}));

View File

@ -0,0 +1,6 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 The angular-translate team, Pascal Precht; Licensed MIT
*/
!function(t,e){"function"==typeof define&&define.amd?define(["messageformat"],function(t){return e(t)}):"object"==typeof module&&module.exports?module.exports=e(require("messageformat")):e(t.MessageFormat)}(this,function(r){function i(u,t,e,n){"use strict";var a={},c=t.get(e),f=new r("en");return angular.isFunction(n)&&n(f),c||(c=t(e)),c.put("en",f),a.setLocale=function(t){(f=c.get(t))||(f=new r(t),angular.isFunction(n)&&n(f),c.put(t,f))},a.getInterpolationIdentifier=function(){return"messageformat"},a.useSanitizeValueStrategy=function(t){return u.useStrategy(t),this},a.interpolate=function(t,e,n,a){e=e||{},e=u.sanitize(e,"params",a);var r=c.get("mf:"+t);if(!r){for(var i in e)if(e.hasOwnProperty(i)){var o=parseInt(e[i],10);angular.isNumber(o)&&""+o===e[i]&&(e[i]=o)}r=f.compile(t),c.put("mf:"+t,r)}var s=r(e);return u.sanitize(s,"text",a)},a}return angular.module("pascalprecht.translate").constant("TRANSLATE_MF_INTERPOLATION_CACHE","$translateMessageFormatInterpolation").provider("$translateMessageFormatInterpolation",function(){"use strict";var a;this.messageFormatConfigurer=function(t){a=t},this.$get=["$translateSanitization","$cacheFactory","TRANSLATE_MF_INTERPOLATION_CACHE",function(t,e,n){return i(t,e,n,a)}]}),i.displayName="$translateMessageFormatInterpolation","pascalprecht.translate"});

View File

@ -0,0 +1,585 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 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 module === 'object' && module.exports) {
// 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, urlTemplate) {
this.name = name;
this.isActive = true;
this.tables = {};
this.priority = priority || 0;
this.langPromises = {};
this.urlTemplate = urlTemplate;
}
/**
* @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) {
//locals
var self = this;
var lastLangPromise = this.langPromises[lang];
var deferred = $q.defer();
//private helper helpers
var fetchData = function () {
return $http(
angular.extend({
method : 'GET',
url : self.parseUrl(self.urlTemplate || urlTemplate, lang)
},
$httpOptions)
);
};
//private helper
var handleNewData = function (data) {
self.tables[lang] = data;
deferred.resolve(data);
};
//private helper
var rejectDeferredWithPartName = function () {
deferred.reject(self.name);
};
//private helper
var tryGettingThisTable = function () {
//data fetching logic
fetchData().then(
function (result) {
handleNewData(result.data);
},
function (errorResponse) {
if (errorHandler) {
errorHandler(self.name, lang, errorResponse).then(handleNewData, rejectDeferredWithPartName);
} else {
rejectDeferredWithPartName();
}
});
};
//loading logic
if (!this.tables[lang]) {
//let's try loading the data
if (!lastLangPromise) {
//this is the first request - just go ahead and hit the server
tryGettingThisTable();
} else {
//this is an additional request after one or more unfinished or failed requests
//chain the deferred off the previous request's promise so that this request conditionally executes
//if the previous request succeeds then the result will be passed through, but if it fails then this request will try again and hit the server
lastLangPromise.then(deferred.resolve, tryGettingThisTable);
}
//retain a reference to the last promise so we can continue the chain if another request is made before any succeed
//you can picture the promise chain as a singly-linked list (formed by the .then handler queues) that's traversed by the execution context
this.langPromises[lang] = deferred.promise;
}
else {
//the part has already been loaded - if lastLangPromise is also undefined then the table has been populated using setPart
//this breaks the promise chain because we're not tying langDeferred's outcome to a previous call's promise handler queues, but we don't care because there's no asynchronous execution context to keep track of anymore
deferred.resolve(this.tables[lang]);
}
return deferred.promise;
};
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.
* @param {string|function} urlTemplate Either a string containing an url pattern (with
* '{part}' and '{lang}') or a function(part, lang)
* returning a string.
*
* @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, urlTemplate) {
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, urlTemplate);
}
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', '$log',
function ($rootScope, $injector, $q, $http, $log) {
/**
* @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 = part.urlTemplate || options.urlTemplate;
});
// workaround for #1781
var structureHasBeenChangedWhileLoading = false;
var dirtyCheckEventCloser = $rootScope.$on('$translatePartialLoaderStructureChanged', function () {
structureHasBeenChangedWhileLoading = true;
});
return $q.all(loaders)
.then(function () {
dirtyCheckEventCloser();
if (structureHasBeenChangedWhileLoading) {
if (!options.__retries) {
// the part structure has been changed while loading (the origin ones)
// this can happen if an addPart/removePart has been invoked right after a $translate.use(lang)
// TODO maybe we can optimize this with the actual list of missing parts
options.__retries = (options.__retries || 0) + 1;
return service(options);
} else {
// the part structure has been changed again while loading (retried one)
// because this could an infinite loop, this will not load another one again
$log.warn('The partial loader has detected a multiple structure change (with addPort/removePart) ' +
'while loading translations. You should consider using promises of $translate.use(lang) and ' +
'$translate.refresh(). Also parts should be added/removed right before an explicit refresh ' +
'if possible.');
}
}
var table = {};
prioritizedParts = getPrioritizedParts();
angular.forEach(prioritizedParts, function (part) {
deepExtend(table, part.tables[options.key]);
});
return table;
}, function () {
dirtyCheckEventCloser();
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, urlTemplate) {
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, urlTemplate);
$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';
}));

View File

@ -0,0 +1,6 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 The angular-translate team, Pascal Precht; Licensed MIT
*/
!function(t,e){"function"==typeof define&&define.amd?define([],function(){return e()}):"object"==typeof module&&module.exports?module.exports=e():e()}(0,function(){function t(){"use strict";function a(t,e,r){this.name=t,this.isActive=!0,this.tables={},this.priority=e||0,this.langPromises={},this.urlTemplate=r}a.prototype.parseUrl=function(t,e){return angular.isFunction(t)?t(this.name,e):t.replace(/\{part\}/g,this.name).replace(/\{lang\}/g,e)},a.prototype.getTable=function(e,t,r,a,n,i){var o=this,s=this.langPromises[e],l=t.defer(),u=function(t){o.tables[e]=t,l.resolve(t)},c=function(){l.reject(o.name)},p=function(){r(angular.extend({method:"GET",url:o.parseUrl(o.urlTemplate||n,e)},a)).then(function(t){u(t.data)},function(t){i?i(o.name,e,t).then(u,c):c()})};return this.tables[e]?l.resolve(this.tables[e]):(s?s.then(l.resolve,p):p(),this.langPromises[e]=l.promise),l.promise};var n={};function i(t){return Object.prototype.hasOwnProperty.call(n,t)}function f(t){return angular.isString(t)&&""!==t}function t(t){if(!f(t))throw new TypeError("Invalid type of a first argument, a non-empty string expected.");return i(t)&&n[t].isActive}function d(){var t=[];for(var e in n)n[e].isActive&&t.push(n[e]);return t.sort(function(t,e){return t.priority-e.priority}),t}this.addPart=function(t,e,r){if(!f(t))throw new TypeError("Couldn't add part, part name has to be a string!");return i(t)||(n[t]=new a(t,e,r)),n[t].isActive=!0,this},this.setPart=function(t,e,r){if(!f(t))throw new TypeError("Couldn't set part.`lang` parameter has to be a string!");if(!f(e))throw new TypeError("Couldn't set part.`part` parameter has to be a string!");if("object"!=typeof r||null===r)throw new TypeError("Couldn't set part. `table` parameter has to be an object!");return i(e)||(n[e]=new a(e),n[e].isActive=!1),n[e].tables[t]=r,this},this.deletePart=function(t){if(!f(t))throw new TypeError("Couldn't delete part, first arg has to be string.");return i(t)&&(n[t].isActive=!1),this},this.isPartAvailable=t,this.$get=["$rootScope","$injector","$q","$http","$log",function(o,s,l,u,c){var p=function(r){if(!f(r.key))throw new TypeError("Unable to load data, a key is not a non-empty string.");if(!f(r.urlTemplate)&&!angular.isFunction(r.urlTemplate))throw new TypeError("Unable to load data, a urlTemplate is not a non-empty string or not a function.");var e=r.loadFailureHandler;if(void 0!==e){if(!angular.isString(e))throw new Error("Unable to load data, a loadFailureHandler is not a string.");e=s.get(e)}var a=[],t=d();angular.forEach(t,function(t){a.push(t.getTable(r.key,l,u,r.$http,r.urlTemplate,e)),t.urlTemplate=t.urlTemplate||r.urlTemplate});var n=!1,i=o.$on("$translatePartialLoaderStructureChanged",function(){n=!0});return l.all(a).then(function(){if(i(),n){if(!r.__retries)return r.__retries=(r.__retries||0)+1,p(r);c.warn("The partial loader has detected a multiple structure change (with addPort/removePart) while loading translations. You should consider using promises of $translate.use(lang) and $translate.refresh(). Also parts should be added/removed right before an explicit refresh if possible.")}var e={};return t=d(),angular.forEach(t,function(t){!function t(e,r){for(var a in r)r[a]&&r[a].constructor&&r[a].constructor===Object?(e[a]=e[a]||{},t(e[a],r[a])):e[a]=r[a];return e}(e,t.tables[r.key])}),e},function(){return i(),l.reject(r.key)})};return p.addPart=function(t,e,r){if(!f(t))throw new TypeError("Couldn't add part, first arg has to be a string");return i(t)?n[t].isActive||(n[t].isActive=!0,o.$emit("$translatePartialLoaderStructureChanged",t)):(n[t]=new a(t,e,r),o.$emit("$translatePartialLoaderStructureChanged",t)),p},p.deletePart=function(r,t){if(!f(r))throw new TypeError("Couldn't delete part, first arg has to be string");if(void 0===t)t=!1;else if("boolean"!=typeof t)throw new TypeError("Invalid type of a second argument, a boolean expected.");if(i(r)){var e=n[r].isActive;if(t){var a=s.get("$translate").loaderCache();"string"==typeof a&&(a=s.get(a)),"object"==typeof a&&angular.forEach(n[r].tables,function(t,e){a.remove(n[r].parseUrl(n[r].urlTemplate,e))}),delete n[r]}else n[r].isActive=!1;e&&o.$emit("$translatePartialLoaderStructureChanged",r)}return p},p.isPartLoaded=function(t,e){return angular.isDefined(n[t])&&angular.isDefined(n[t].tables[e])},p.getRegisteredParts=function(){var e=[];return angular.forEach(n,function(t){t.isActive&&e.push(t.name)}),e},p.isPartAvailable=t,p}]}return angular.module("pascalprecht.translate").provider("$translatePartialLoader",t),t.displayName="$translatePartialLoader","pascalprecht.translate"});

View File

@ -0,0 +1,112 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 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 module === 'object' && module.exports) {
// 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 () {
$translateStaticFilesLoader.$inject = ['$q', '$http'];
angular.module('pascalprecht.translate')
/**
* @ngdoc object
* @name pascalprecht.translate.$translateStaticFilesLoader
* @requires $q
* @requires $http
*
* @description
* Creates a loading function for a typical static file url pattern:
* "lang-en_US.json", "lang-de_DE.json", etc. Using this builder,
* the response of these urls must be an object of key-value pairs.
*
* @param {object} options Options object, which gets prefix, suffix, key, and fileMap
*/
.factory('$translateStaticFilesLoader', $translateStaticFilesLoader);
function $translateStaticFilesLoader($q, $http) {
'use strict';
return function (options) {
if (!options || (!angular.isArray(options.files) && (!angular.isString(options.prefix) || !angular.isString(options.suffix)))) {
throw new Error('Couldn\'t load static files, no files and prefix or suffix specified!');
}
if (!options.files) {
options.files = [{
prefix: options.prefix,
suffix: options.suffix
}];
}
var load = function (file) {
if (!file || (!angular.isString(file.prefix) || !angular.isString(file.suffix))) {
throw new Error('Couldn\'t load static file, no prefix or suffix specified!');
}
var fileUrl = [
file.prefix,
options.key,
file.suffix
].join('');
if (angular.isObject(options.fileMap) && options.fileMap[fileUrl]) {
fileUrl = options.fileMap[fileUrl];
}
return $http(angular.extend({
url: fileUrl,
method: 'GET'
}, options.$http))
.then(function(result) {
return result.data;
}, function () {
return $q.reject(options.key);
});
};
var promises = [],
length = options.files.length;
for (var i = 0; i < length; i++) {
promises.push(load({
prefix: options.files[i].prefix,
key: options.key,
suffix: options.files[i].suffix
}));
}
return $q.all(promises)
.then(function (data) {
var length = data.length,
mergedData = {};
for (var i = 0; i < length; i++) {
for (var key in data[i]) {
mergedData[key] = data[i][key];
}
}
return mergedData;
});
};
}
$translateStaticFilesLoader.displayName = '$translateStaticFilesLoader';
return 'pascalprecht.translate';
}));

View File

@ -0,0 +1,6 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 The angular-translate team, Pascal Precht; Licensed MIT
*/
!function(e,i){"function"==typeof define&&define.amd?define([],function(){return i()}):"object"==typeof module&&module.exports?module.exports=i():i()}(0,function(){function e(n,a){"use strict";return function(r){if(!(r&&(angular.isArray(r.files)||angular.isString(r.prefix)&&angular.isString(r.suffix))))throw new Error("Couldn't load static files, no files and prefix or suffix specified!");r.files||(r.files=[{prefix:r.prefix,suffix:r.suffix}]);for(var e=function(e){if(!e||!angular.isString(e.prefix)||!angular.isString(e.suffix))throw new Error("Couldn't load static file, no prefix or suffix specified!");var i=[e.prefix,r.key,e.suffix].join("");return angular.isObject(r.fileMap)&&r.fileMap[i]&&(i=r.fileMap[i]),a(angular.extend({url:i,method:"GET"},r.$http)).then(function(e){return e.data},function(){return n.reject(r.key)})},i=[],t=r.files.length,f=0;f<t;f++)i.push(e({prefix:r.files[f].prefix,key:r.key,suffix:r.files[f].suffix}));return n.all(i).then(function(e){for(var i=e.length,r={},t=0;t<i;t++)for(var f in e[t])r[f]=e[t][f];return r})}}return e.$inject=["$q","$http"],angular.module("pascalprecht.translate").factory("$translateStaticFilesLoader",e),e.displayName="$translateStaticFilesLoader","pascalprecht.translate"});

View File

@ -0,0 +1,73 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 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 module === 'object' && module.exports) {
// 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 () {
$translateUrlLoader.$inject = ['$q', '$http'];
angular.module('pascalprecht.translate')
/**
* @ngdoc object
* @name pascalprecht.translate.$translateUrlLoader
* @requires $q
* @requires $http
*
* @description
* Creates a loading function for a typical dynamic url pattern:
* "locale.php?lang=en_US", "locale.php?lang=de_DE", "locale.php?language=nl_NL" etc.
* Prefixing the specified url, the current requested, language id will be applied
* with "?{queryParameter}={key}".
* Using this service, the response of these urls must be an object of
* key-value pairs.
*
* @param {object} options Options object, which gets the url, key and
* optional queryParameter ('lang' is used by default).
*/
.factory('$translateUrlLoader', $translateUrlLoader);
function $translateUrlLoader($q, $http) {
'use strict';
return function (options) {
if (!options || !options.url) {
throw new Error('Couldn\'t use urlLoader since no url is given!');
}
var requestParams = {};
requestParams[options.queryParameter || 'lang'] = options.key;
return $http(angular.extend({
url: options.url,
params: requestParams,
method: 'GET'
}, options.$http))
.then(function(result) {
return result.data;
}, function () {
return $q.reject(options.key);
});
};
}
$translateUrlLoader.displayName = '$translateUrlLoader';
return 'pascalprecht.translate';
}));

View File

@ -0,0 +1,6 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 The angular-translate team, Pascal Precht; Licensed MIT
*/
!function(e,t){"function"==typeof define&&define.amd?define([],function(){return t()}):"object"==typeof module&&module.exports?module.exports=t():t()}(0,function(){function e(r,n){"use strict";return function(e){if(!e||!e.url)throw new Error("Couldn't use urlLoader since no url is given!");var t={};return t[e.queryParameter||"lang"]=e.key,n(angular.extend({url:e.url,params:t,method:"GET"},e.$http)).then(function(e){return e.data},function(){return r.reject(e.key)})}}return e.$inject=["$q","$http"],angular.module("pascalprecht.translate").factory("$translateUrlLoader",e),e.displayName="$translateUrlLoader","pascalprecht.translate"});

View File

@ -0,0 +1,121 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 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 module === 'object' && module.exports) {
// 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 () {
$translateCookieStorageFactory.$inject = ['$injector'];
angular.module('pascalprecht.translate')
/**
* @ngdoc object
* @name pascalprecht.translate.$translateCookieStorage
* @requires $cookieStore
*
* @description
* Abstraction layer for cookieStore. This service is used when telling angular-translate
* to use cookieStore as storage.
*
*/
.factory('$translateCookieStorage', $translateCookieStorageFactory);
function $translateCookieStorageFactory($injector) {
'use strict';
// Since AngularJS 1.4, $cookieStore is deprecated
var delegate;
if (angular.version.major === 1 && angular.version.minor >= 4) {
var $cookies = $injector.get('$cookies');
delegate = {
get : function (key) {
return $cookies.get(key);
},
put : function (key, value) {
$cookies.put(key, value);
}
};
} else {
var $cookieStore = $injector.get('$cookieStore');
delegate = {
get : function (key) {
return $cookieStore.get(key);
},
put : function (key, value) {
$cookieStore.put(key, value);
}
};
}
var $translateCookieStorage = {
/**
* @ngdoc function
* @name pascalprecht.translate.$translateCookieStorage#get
* @methodOf pascalprecht.translate.$translateCookieStorage
*
* @description
* Returns an item from cookieStorage by given name.
*
* @param {string} name Item name
* @return {string} Value of item name
*/
get : function (name) {
return delegate.get(name);
},
/**
* @ngdoc function
* @name pascalprecht.translate.$translateCookieStorage#set
* @methodOf pascalprecht.translate.$translateCookieStorage
*
* @description
* Sets an item in cookieStorage by given name.
*
* @deprecated use #put
*
* @param {string} name Item name
* @param {string} value Item value
*/
set : function (name, value) {
delegate.put(name, value);
},
/**
* @ngdoc function
* @name pascalprecht.translate.$translateCookieStorage#put
* @methodOf pascalprecht.translate.$translateCookieStorage
*
* @description
* Sets an item in cookieStorage by given name.
*
* @param {string} name Item name
* @param {string} value Item value
*/
put : function (name, value) {
delegate.put(name, value);
}
};
return $translateCookieStorage;
}
$translateCookieStorageFactory.displayName = '$translateCookieStorage';
return 'pascalprecht.translate';
}));

View File

@ -0,0 +1,6 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 The angular-translate team, Pascal Precht; Licensed MIT
*/
!function(t,e){"function"==typeof define&&define.amd?define([],function(){return e()}):"object"==typeof module&&module.exports?module.exports=e():e()}(0,function(){function t(t){"use strict";var n;if(1===angular.version.major&&4<=angular.version.minor){var o=t.get("$cookies");n={get:function(t){return o.get(t)},put:function(t,e){o.put(t,e)}}}else{var r=t.get("$cookieStore");n={get:function(t){return r.get(t)},put:function(t,e){r.put(t,e)}}}return{get:function(t){return n.get(t)},set:function(t,e){n.put(t,e)},put:function(t,e){n.put(t,e)}}}return t.$inject=["$injector"],angular.module("pascalprecht.translate").factory("$translateCookieStorage",t),t.displayName="$translateCookieStorage","pascalprecht.translate"});

View File

@ -0,0 +1,123 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 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 module === 'object' && module.exports) {
// 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 () {
$translateLocalStorageFactory.$inject = ['$window', '$translateCookieStorage'];
angular.module('pascalprecht.translate')
/**
* @ngdoc object
* @name pascalprecht.translate.$translateLocalStorage
* @requires $window
* @requires $translateCookieStorage
*
* @description
* Abstraction layer for localStorage. This service is used when telling angular-translate
* to use localStorage as storage.
*
*/
.factory('$translateLocalStorage', $translateLocalStorageFactory);
function $translateLocalStorageFactory($window, $translateCookieStorage) {
'use strict';
// Setup adapter
var localStorageAdapter = (function(){
var langKey;
return {
/**
* @ngdoc function
* @name pascalprecht.translate.$translateLocalStorage#get
* @methodOf pascalprecht.translate.$translateLocalStorage
*
* @description
* Returns an item from localStorage by given name.
*
* @param {string} name Item name
* @return {string} Value of item name
*/
get: function (name) {
if(!langKey) {
langKey = $window.localStorage.getItem(name);
}
return langKey;
},
/**
* @ngdoc function
* @name pascalprecht.translate.$translateLocalStorage#set
* @methodOf pascalprecht.translate.$translateLocalStorage
*
* @description
* Sets an item in localStorage by given name.
*
* @deprecated use #put
*
* @param {string} name Item name
* @param {string} value Item value
*/
set: function (name, value) {
langKey=value;
$window.localStorage.setItem(name, value);
},
/**
* @ngdoc function
* @name pascalprecht.translate.$translateLocalStorage#put
* @methodOf pascalprecht.translate.$translateLocalStorage
*
* @description
* Sets an item in localStorage by given name.
*
* @param {string} name Item name
* @param {string} value Item value
*/
put: function (name, value) {
langKey=value;
$window.localStorage.setItem(name, value);
}
};
}());
var hasLocalStorageSupport = 'localStorage' in $window;
if (hasLocalStorageSupport) {
var testKey = 'pascalprecht.translate.storageTest';
try {
// this check have to be wrapped within a try/catch because on
// a SecurityError: Dom Exception 18 on iOS
if ($window.localStorage !== null) {
$window.localStorage.setItem(testKey, 'foo');
$window.localStorage.removeItem(testKey);
hasLocalStorageSupport = true;
} else {
hasLocalStorageSupport = false;
}
} catch (e){
hasLocalStorageSupport = false;
}
}
var $translateLocalStorage = hasLocalStorageSupport ? localStorageAdapter : $translateCookieStorage;
return $translateLocalStorage;
}
$translateLocalStorageFactory.displayName = '$translateLocalStorageFactory';
return 'pascalprecht.translate';
}));

View File

@ -0,0 +1,6 @@
/*!
* angular-translate - v2.18.2 - 2020-01-04
*
* Copyright (c) 2020 The angular-translate team, Pascal Precht; Licensed MIT
*/
!function(t,e){"function"==typeof define&&define.amd?define([],function(){return e()}):"object"==typeof module&&module.exports?module.exports=e():e()}(0,function(){function t(a,t){"use strict";var o,e={get:function(t){return o||(o=a.localStorage.getItem(t)),o},set:function(t,e){o=e,a.localStorage.setItem(t,e)},put:function(t,e){o=e,a.localStorage.setItem(t,e)}},r="localStorage"in a;if(r){var n="pascalprecht.translate.storageTest";try{r=null!==a.localStorage&&(a.localStorage.setItem(n,"foo"),a.localStorage.removeItem(n),!0)}catch(t){r=!1}}return r?e:t}return t.$inject=["$window","$translateCookieStorage"],angular.module("pascalprecht.translate").factory("$translateLocalStorage",t),t.displayName="$translateLocalStorageFactory","pascalprecht.translate"});

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long