Fraction
-
-
+
diff --git a/activities/FractionBounce.activity/js/components/SugarL10n.js b/activities/FractionBounce.activity/js/components/SugarL10n.js
index f18b18f8c..3721caeb5 100644
--- a/activities/FractionBounce.activity/js/components/SugarL10n.js
+++ b/activities/FractionBounce.activity/js/components/SugarL10n.js
@@ -6,7 +6,6 @@ Vue.component('sugar-localization', {
l10n: null,
code: null,
dictionary: null,
- eventReceived: false,
activityInitialized: false,
units: [
{ name: 'Years', factor: 356 * 24 * 60 * 60 },
@@ -16,70 +15,92 @@ Vue.component('sugar-localization', {
{ name: 'Hours', factor: 60 * 60 },
{ name: 'Minutes', factor: 60 }
],
- }
+ };
},
computed: {
readyToEmit: function () {
- return (this.dictionary != null) && this.activityInitialized;
- }
+ return this.dictionary != null && this.activityInitialized;
+ },
},
watch: {
readyToEmit: function (newVal, oldVal) {
if (newVal) {
- this.$emit("localized");
- this.eventReceived = true;
+ this.$emit('localized');
}
- }
+ },
},
mounted: function () {
- var vm = this;
- if (vm.l10n == null) {
- requirejs(["sugar-web/env", "webL10n"], function (env, webL10n) {
- env.getEnvironment(function (err, environment) {
- vm.l10n = webL10n;
- var defaultLanguage = (typeof chrome != 'undefined' && chrome.app && chrome.app.runtime) ? chrome.i18n.getUILanguage() : navigator.language;
- var language = environment.user ? environment.user.language : defaultLanguage;
- webL10n.language.code = language;
- window.addEventListener("localized", function () {
- if (!vm.eventReceived) {
- vm.code = language;
- vm.dictionary = vm.l10n.dictionary;
- } else if (webL10n.language.code != language) {
- webL10n.language.code = language;
- }
- });
- });
- });
- //Activity initialization check
- var SugarActivity = vm.$root.$children.find(function (child) {
- return child.$options.name == 'SugarActivity';
- });
- SugarActivity.$on('initialized', function () {
- vm.activityInitialized = true;
+ const vm = this;
+
+ requirejs(['sugar-web/env'], function (env) {
+ env.getEnvironment((err, environment) => {
+ // Get default language
+ const defaultLanguage =
+ typeof chrome !== 'undefined' &&
+ chrome.app &&
+ chrome.app.runtime
+ ? chrome.i18n.getUILanguage()
+ : navigator.language;
+ const language = environment.user
+ ? environment.user.language
+ : defaultLanguage;
+
+ vm.loadLanguageFile(language);
});
- }
+ });
+
+ // Activity initialization check
+ const SugarActivity = vm.$root.$children.find(function (child) {
+ return child.$options.name == 'SugarActivity';
+ });
+ SugarActivity.$on('initialized', function () {
+ vm.activityInitialized = true;
+ });
},
+
methods: {
- // Get a string with parameters
+ loadLanguageFile: function (language) {
+ const vm = this;
+ requirejs(['lib/i18next.min.js', 'lib/axios.min.js'], function (i18next, axios) {
+ axios.get(`./locales/${language}.json`).then((response) => {
+ i18next.init(
+ {
+ lng: language,
+ fallbackLng: 'en',
+ resources: {
+ [language]: {
+ translation: response.data
+ }
+ },
+ },
+ () => {
+ vm.l10n = i18next;
+ vm.code = i18next.language;
+ vm.dictionary = i18next.getResourceBundle(i18next.language, 'translation');
+ }
+ );
+ }).catch((error) => {
+ vm.loadLanguageFile('en'); // Load default language
+ console.log(error);
+ });
+ });
+ },
+
+ // Get a string with parameter
get: function (str, params) {
- var out = '';
-
+ let out = '';
+
if (!this.dictionary) {
out = str;
} else {
- var item = this.dictionary[str];
- if (!item || !item.textContent) {
- out = str;
- } else {
- out = item.textContent;
- }
+ out = this.dictionary[str] || str;
}
-
+
// Check params
- if(params) {
- var paramsInString = out.match(/{{\s*[\w\.]+\s*}}/g);
- for (var i in paramsInString) {
- var param = paramsInString[i].match(/[\w\.]+/)[0];
+ if (params) {
+ let paramsInString = out.match(/{{\s*[\w\.]+\s*}}/g);
+ for (let i in paramsInString) {
+ let param = paramsInString[i].match(/[\w\.]+/)[0];
if (params[param]) {
out = out.replace(paramsInString[i], params[param]);
}
@@ -90,22 +111,22 @@ Vue.component('sugar-localization', {
// Get values for a set of strings on the form of {stringKey1: '', stringKey2: '', ...}
localize: function (strings) {
- var vm = this;
- Object.keys(strings).forEach(function (key, index) {
+ const vm = this;
+ Object.keys(strings).forEach((key, index) => {
strings[key] = vm.get(key.substr(6));
});
},
// Convert a UNIX timestamp to Sugarizer time elapsed string
localizeTimestamp: function (timestamp) {
- var maxlevel = 2;
- var levels = 0;
- var time_period = '';
- var elapsed_seconds = ((new Date().getTime()) - timestamp) / 1000;
- for (var i = 0; i < this.units.length; i++) {
- var factor = this.units[i].factor;
-
- var elapsed_units = Math.floor(elapsed_seconds / factor);
+ const maxlevel = 2;
+ const levels = 0;
+ let time_period = '';
+ let elapsed_seconds = (Date.now() - timestamp) / 1000;
+ for (let i = 0; i < this.units.length; i++) {
+ let factor = this.units[i].factor;
+
+ let elapsed_units = Math.floor(elapsed_seconds / factor);
if (elapsed_units > 0) {
if (levels > 0)
time_period += ',';
@@ -123,10 +144,10 @@ Vue.component('sugar-localization', {
}
if (levels == 0) {
- return this.get("SecondsAgo");
+ return this.get('SecondsAgo');
}
- return this.get("Ago", { time: time_period });
- }
- }
+ return this.get('Ago', { time: time_period });
+ },
+ },
});
diff --git a/activities/FractionBounce.activity/lib/axios.min.js b/activities/FractionBounce.activity/lib/axios.min.js
new file mode 100644
index 000000000..fc6c8b618
--- /dev/null
+++ b/activities/FractionBounce.activity/lib/axios.min.js
@@ -0,0 +1,3 @@
+/* axios v0.21.1 | (c) 2020 by Matt Zabriskie */
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.axios=t():e.axios=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";function r(e){var t=new i(e),n=s(i.prototype.request,t);return o.extend(n,i.prototype,t),o.extend(n,t),n}var o=n(2),s=n(3),i=n(4),a=n(22),u=n(10),c=r(u);c.Axios=i,c.create=function(e){return r(a(c.defaults,e))},c.Cancel=n(23),c.CancelToken=n(24),c.isCancel=n(9),c.all=function(e){return Promise.all(e)},c.spread=n(25),c.isAxiosError=n(26),e.exports=c,e.exports.default=c},function(e,t,n){"use strict";function r(e){return"[object Array]"===R.call(e)}function o(e){return"undefined"==typeof e}function s(e){return null!==e&&!o(e)&&null!==e.constructor&&!o(e.constructor)&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}function i(e){return"[object ArrayBuffer]"===R.call(e)}function a(e){return"undefined"!=typeof FormData&&e instanceof FormData}function u(e){var t;return t="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer}function c(e){return"string"==typeof e}function f(e){return"number"==typeof e}function p(e){return null!==e&&"object"==typeof e}function d(e){if("[object Object]"!==R.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function l(e){return"[object Date]"===R.call(e)}function h(e){return"[object File]"===R.call(e)}function m(e){return"[object Blob]"===R.call(e)}function y(e){return"[object Function]"===R.call(e)}function g(e){return p(e)&&y(e.pipe)}function v(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams}function x(e){return e.replace(/^\s*/,"").replace(/\s*$/,"")}function w(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&("undefined"!=typeof window&&"undefined"!=typeof document)}function b(e,t){if(null!==e&&"undefined"!=typeof e)if("object"!=typeof e&&(e=[e]),r(e))for(var n=0,o=e.length;n=200&&e<300}};u.headers={common:{Accept:"application/json, text/plain, */*"}},s.forEach(["delete","get","head"],function(e){u.headers[e]={}}),s.forEach(["post","put","patch"],function(e){u.headers[e]=s.merge(a)}),e.exports=u},function(e,t,n){"use strict";var r=n(2);e.exports=function(e,t){r.forEach(e,function(n,r){r!==t&&r.toUpperCase()===t.toUpperCase()&&(e[t]=n,delete e[r])})}},function(e,t,n){"use strict";var r=n(2),o=n(13),s=n(16),i=n(5),a=n(17),u=n(20),c=n(21),f=n(14);e.exports=function(e){return new Promise(function(t,n){var p=e.data,d=e.headers;r.isFormData(p)&&delete d["Content-Type"];var l=new XMLHttpRequest;if(e.auth){var h=e.auth.username||"",m=e.auth.password?unescape(encodeURIComponent(e.auth.password)):"";d.Authorization="Basic "+btoa(h+":"+m)}var y=a(e.baseURL,e.url);if(l.open(e.method.toUpperCase(),i(y,e.params,e.paramsSerializer),!0),l.timeout=e.timeout,l.onreadystatechange=function(){if(l&&4===l.readyState&&(0!==l.status||l.responseURL&&0===l.responseURL.indexOf("file:"))){var r="getAllResponseHeaders"in l?u(l.getAllResponseHeaders()):null,s=e.responseType&&"text"!==e.responseType?l.response:l.responseText,i={data:s,status:l.status,statusText:l.statusText,headers:r,config:e,request:l};o(t,n,i),l=null}},l.onabort=function(){l&&(n(f("Request aborted",e,"ECONNABORTED",l)),l=null)},l.onerror=function(){n(f("Network Error",e,null,l)),l=null},l.ontimeout=function(){var t="timeout of "+e.timeout+"ms exceeded";e.timeoutErrorMessage&&(t=e.timeoutErrorMessage),n(f(t,e,"ECONNABORTED",l)),l=null},r.isStandardBrowserEnv()){var g=(e.withCredentials||c(y))&&e.xsrfCookieName?s.read(e.xsrfCookieName):void 0;g&&(d[e.xsrfHeaderName]=g)}if("setRequestHeader"in l&&r.forEach(d,function(e,t){"undefined"==typeof p&&"content-type"===t.toLowerCase()?delete d[t]:l.setRequestHeader(t,e)}),r.isUndefined(e.withCredentials)||(l.withCredentials=!!e.withCredentials),e.responseType)try{l.responseType=e.responseType}catch(t){if("json"!==e.responseType)throw t}"function"==typeof e.onDownloadProgress&&l.addEventListener("progress",e.onDownloadProgress),"function"==typeof e.onUploadProgress&&l.upload&&l.upload.addEventListener("progress",e.onUploadProgress),e.cancelToken&&e.cancelToken.promise.then(function(e){l&&(l.abort(),n(e),l=null)}),p||(p=null),l.send(p)})}},function(e,t,n){"use strict";var r=n(14);e.exports=function(e,t,n){var o=n.config.validateStatus;n.status&&o&&!o(n.status)?t(r("Request failed with status code "+n.status,n.config,null,n.request,n)):e(n)}},function(e,t,n){"use strict";var r=n(15);e.exports=function(e,t,n,o,s){var i=new Error(e);return r(i,t,n,o,s)}},function(e,t){"use strict";e.exports=function(e,t,n,r,o){return e.config=t,n&&(e.code=n),e.request=r,e.response=o,e.isAxiosError=!0,e.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code}},e}},function(e,t,n){"use strict";var r=n(2);e.exports=r.isStandardBrowserEnv()?function(){return{write:function(e,t,n,o,s,i){var a=[];a.push(e+"="+encodeURIComponent(t)),r.isNumber(n)&&a.push("expires="+new Date(n).toGMTString()),r.isString(o)&&a.push("path="+o),r.isString(s)&&a.push("domain="+s),i===!0&&a.push("secure"),document.cookie=a.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}}():function(){return{write:function(){},read:function(){return null},remove:function(){}}}()},function(e,t,n){"use strict";var r=n(18),o=n(19);e.exports=function(e,t){return e&&!r(t)?o(e,t):t}},function(e,t){"use strict";e.exports=function(e){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e)}},function(e,t){"use strict";e.exports=function(e,t){return t?e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,""):e}},function(e,t,n){"use strict";var r=n(2),o=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];e.exports=function(e){var t,n,s,i={};return e?(r.forEach(e.split("\n"),function(e){if(s=e.indexOf(":"),t=r.trim(e.substr(0,s)).toLowerCase(),n=r.trim(e.substr(s+1)),t){if(i[t]&&o.indexOf(t)>=0)return;"set-cookie"===t?i[t]=(i[t]?i[t]:[]).concat([n]):i[t]=i[t]?i[t]+", "+n:n}}),i):i}},function(e,t,n){"use strict";var r=n(2);e.exports=r.isStandardBrowserEnv()?function(){function e(e){var t=e;return n&&(o.setAttribute("href",t),t=o.href),o.setAttribute("href",t),{href:o.href,protocol:o.protocol?o.protocol.replace(/:$/,""):"",host:o.host,search:o.search?o.search.replace(/^\?/,""):"",hash:o.hash?o.hash.replace(/^#/,""):"",hostname:o.hostname,port:o.port,pathname:"/"===o.pathname.charAt(0)?o.pathname:"/"+o.pathname}}var t,n=/(msie|trident)/i.test(navigator.userAgent),o=document.createElement("a");return t=e(window.location.href),function(n){var o=r.isString(n)?e(n):n;return o.protocol===t.protocol&&o.host===t.host}}():function(){return function(){return!0}}()},function(e,t,n){"use strict";var r=n(2);e.exports=function(e,t){function n(e,t){return r.isPlainObject(e)&&r.isPlainObject(t)?r.merge(e,t):r.isPlainObject(t)?r.merge({},t):r.isArray(t)?t.slice():t}function o(o){r.isUndefined(t[o])?r.isUndefined(e[o])||(s[o]=n(void 0,e[o])):s[o]=n(e[o],t[o])}t=t||{};var s={},i=["url","method","data"],a=["headers","auth","proxy","params"],u=["baseURL","transformRequest","transformResponse","paramsSerializer","timeout","timeoutMessage","withCredentials","adapter","responseType","xsrfCookieName","xsrfHeaderName","onUploadProgress","onDownloadProgress","decompress","maxContentLength","maxBodyLength","maxRedirects","transport","httpAgent","httpsAgent","cancelToken","socketPath","responseEncoding"],c=["validateStatus"];r.forEach(i,function(e){r.isUndefined(t[e])||(s[e]=n(void 0,t[e]))}),r.forEach(a,o),r.forEach(u,function(o){r.isUndefined(t[o])?r.isUndefined(e[o])||(s[o]=n(void 0,e[o])):s[o]=n(void 0,t[o])}),r.forEach(c,function(r){r in t?s[r]=n(e[r],t[r]):r in e&&(s[r]=n(void 0,e[r]))});var f=i.concat(a).concat(u).concat(c),p=Object.keys(e).concat(Object.keys(t)).filter(function(e){return f.indexOf(e)===-1});return r.forEach(p,o),s}},function(e,t){"use strict";function n(e){this.message=e}n.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},n.prototype.__CANCEL__=!0,e.exports=n},function(e,t,n){"use strict";function r(e){if("function"!=typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise(function(e){t=e});var n=this;e(function(e){n.reason||(n.reason=new o(e),t(n.reason))})}var o=n(23);r.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},r.source=function(){var e,t=new r(function(t){e=t});return{token:t,cancel:e}},e.exports=r},function(e,t){"use strict";e.exports=function(e){return function(t){return e.apply(null,t)}}},function(e,t){"use strict";e.exports=function(e){return"object"==typeof e&&e.isAxiosError===!0}}])});
+//# sourceMappingURL=axios.min.map
\ No newline at end of file
diff --git a/activities/FractionBounce.activity/lib/i18next.min.js b/activities/FractionBounce.activity/lib/i18next.min.js
new file mode 100644
index 000000000..00b2fd83e
--- /dev/null
+++ b/activities/FractionBounce.activity/lib/i18next.min.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).i18next=t()}(this,function(){"use strict";function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}function t(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function n(e){for(var n=1;n1&&void 0!==arguments[1]?arguments[1]:{};i(this,e),this.init(t,n)}return r(e,[{key:"init",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};this.prefix=t.prefix||"i18next:",this.logger=e||p,this.options=t,this.debug=t.debug}},{key:"setDebug",value:function(e){this.debug=e}},{key:"log",value:function(){for(var e=arguments.length,t=new Array(e),n=0;n1?t-1:0),i=1;i-1?e.replace(/###/g,"."):e}function o(){return!e||"string"==typeof e}for(var r="string"!=typeof t?[].concat(t):t.split(".");r.length>1;){if(o())return{};var a=i(r.shift());!e[a]&&n&&(e[a]=new n),e=Object.prototype.hasOwnProperty.call(e,a)?e[a]:{}}return o()?{}:{obj:e,k:i(r.shift())}}function y(e,t,n){var i=v(e,t,Object);i.obj[i.k]=n}function m(e,t){var n=v(e,t),i=n.obj,o=n.k;if(i)return i[o]}function b(e,t,n){var i=m(e,n);return void 0!==i?i:m(t,n)}function k(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}var x={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};function S(e){return"string"==typeof e?e.replace(/[&<>"'\/]/g,function(e){return x[e]}):e}var w="undefined"!=typeof window&&window.navigator&&window.navigator.userAgent&&window.navigator.userAgent.indexOf("MSIE")>-1;var L=function(e){function t(e){var n,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{ns:["translation"],defaultNS:"translation"};return i(this,t),n=s(this,u(t).call(this)),w&&f.call(a(n)),n.data=e||{},n.options=o,void 0===n.options.keySeparator&&(n.options.keySeparator="."),void 0===n.options.ignoreJSONStructure&&(n.options.ignoreJSONStructure=!0),n}return c(t,f),r(t,[{key:"addNamespaces",value:function(e){this.options.ns.indexOf(e)<0&&this.options.ns.push(e)}},{key:"removeNamespaces",value:function(e){var t=this.options.ns.indexOf(e);t>-1&&this.options.ns.splice(t,1)}},{key:"getResource",value:function(e,t,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=void 0!==i.keySeparator?i.keySeparator:this.options.keySeparator,r=void 0!==i.ignoreJSONStructure?i.ignoreJSONStructure:this.options.ignoreJSONStructure,a=[e,t];n&&"string"!=typeof n&&(a=a.concat(n)),n&&"string"==typeof n&&(a=a.concat(o?n.split(o):n)),e.indexOf(".")>-1&&(a=e.split("."));var s=m(this.data,a);return s||!r||"string"!=typeof n?s:function e(t,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:".";if(t){if(t[n])return t[n];for(var o=n.split(i),r=t,a=0;aa+s;)s++,l=r[u=o.slice(a,a+s).join(i)];if(void 0===l)return;if("string"==typeof l)return l;if(u&&"string"==typeof l[u])return l[u];var c=o.slice(a+s).join(i);return c?e(l,c,i):void 0}r=r[o[a]]}return r}}(this.data&&this.data[e]&&this.data[e][t],n,o)}},{key:"addResource",value:function(e,t,n,i){var o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{silent:!1},r=this.options.keySeparator;void 0===r&&(r=".");var a=[e,t];n&&(a=a.concat(r?n.split(r):n)),e.indexOf(".")>-1&&(i=t,t=(a=e.split("."))[1]),this.addNamespaces(t),y(this.data,a,i),o.silent||this.emit("added",e,t,n,i)}},{key:"addResources",value:function(e,t,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{silent:!1};for(var o in n)"string"!=typeof n[o]&&"[object Array]"!==Object.prototype.toString.apply(n[o])||this.addResource(e,t,o,n[o],{silent:!0});i.silent||this.emit("added",e,t,n)}},{key:"addResourceBundle",value:function(e,t,i,o,r){var a=arguments.length>5&&void 0!==arguments[5]?arguments[5]:{silent:!1},s=[e,t];e.indexOf(".")>-1&&(o=i,i=t,t=(s=e.split("."))[1]),this.addNamespaces(t);var u=m(this.data,s)||{};o?function e(t,n,i){for(var o in n)"__proto__"!==o&&"constructor"!==o&&(o in t?"string"==typeof t[o]||t[o]instanceof String||"string"==typeof n[o]||n[o]instanceof String?i&&(t[o]=n[o]):e(t[o],n[o],i):t[o]=n[o]);return t}(u,i,r):u=n({},u,i),y(this.data,s,u),a.silent||this.emit("added",e,t,i)}},{key:"removeResourceBundle",value:function(e,t){this.hasResourceBundle(e,t)&&delete this.data[e][t],this.removeNamespaces(t),this.emit("removed",e,t)}},{key:"hasResourceBundle",value:function(e,t){return void 0!==this.getResource(e,t)}},{key:"getResourceBundle",value:function(e,t){return t||(t=this.options.defaultNS),"v1"===this.options.compatibilityAPI?n({},{},this.getResource(e,t)):this.getResource(e,t)}},{key:"getDataByLanguage",value:function(e){return this.data[e]}},{key:"toJSON",value:function(){return this.data}}]),t}(),O={processors:{},addPostProcessor:function(e){this.processors[e.name]=e},handle:function(e,t,n,i,o){var r=this;return e.forEach(function(e){r.processors[e]&&(t=r.processors[e].process(t,n,i,o))}),t}},N={},R=function(t){function o(e){var t,n,r,l,c=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return i(this,o),t=s(this,u(o).call(this)),w&&f.call(a(t)),n=["resourceStore","languageUtils","pluralResolver","interpolator","backendConnector","i18nFormat","utils"],r=e,l=a(t),n.forEach(function(e){r[e]&&(l[e]=r[e])}),t.options=c,void 0===t.options.keySeparator&&(t.options.keySeparator="."),t.logger=g.create("translator"),t}return c(o,f),r(o,[{key:"changeLanguage",value:function(e){e&&(this.language=e)}},{key:"exists",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{interpolation:{}},n=this.resolve(e,t);return n&&void 0!==n.res}},{key:"extractFromKey",value:function(e,t){var n=void 0!==t.nsSeparator?t.nsSeparator:this.options.nsSeparator;void 0===n&&(n=":");var i=void 0!==t.keySeparator?t.keySeparator:this.options.keySeparator,o=t.ns||this.options.defaultNS;if(n&&e.indexOf(n)>-1){var r=e.match(this.interpolator.nestingRegexp);if(r&&r.length>0)return{key:e,namespaces:o};var a=e.split(n);(n!==i||n===i&&this.options.ns.indexOf(a[0])>-1)&&(o=a.shift()),e=a.join(i)}return"string"==typeof o&&(o=[o]),{key:e,namespaces:o}}},{key:"translate",value:function(t,i,r){var a=this;if("object"!==e(i)&&this.options.overloadTranslationOptionHandler&&(i=this.options.overloadTranslationOptionHandler(arguments)),i||(i={}),null==t)return"";Array.isArray(t)||(t=[String(t)]);var s=void 0!==i.keySeparator?i.keySeparator:this.options.keySeparator,u=this.extractFromKey(t[t.length-1],i),l=u.key,c=u.namespaces,p=c[c.length-1],g=i.lng||this.language,f=i.appendNamespaceToCIMode||this.options.appendNamespaceToCIMode;if(g&&"cimode"===g.toLowerCase()){if(f){var h=i.nsSeparator||this.options.nsSeparator;return p+h+l}return l}var d=this.resolve(t,i),v=d&&d.res,y=d&&d.usedKey||l,m=d&&d.exactUsedKey||l,b=Object.prototype.toString.apply(v),k=void 0!==i.joinArrays?i.joinArrays:this.options.joinArrays,x=!this.i18nFormat||this.i18nFormat.handleAsObject;if(x&&v&&("string"!=typeof v&&"boolean"!=typeof v&&"number"!=typeof v)&&["[object Number]","[object Function]","[object RegExp]"].indexOf(b)<0&&("string"!=typeof k||"[object Array]"!==b)){if(!i.returnObjects&&!this.options.returnObjects)return this.logger.warn("accessing an object - but returnObjects options is not enabled!"),this.options.returnedObjectHandler?this.options.returnedObjectHandler(y,v,i):"key '".concat(l," (").concat(this.language,")' returned an object instead of string.");if(s){var S="[object Array]"===b,w=S?[]:{},L=S?m:y;for(var O in v)if(Object.prototype.hasOwnProperty.call(v,O)){var N="".concat(L).concat(s).concat(O);w[O]=this.translate(N,n({},i,{joinArrays:!1,ns:c})),w[O]===N&&(w[O]=v[O])}v=w}}else if(x&&"string"==typeof k&&"[object Array]"===b)(v=v.join(k))&&(v=this.extendTranslation(v,t,i,r));else{var R=!1,C=!1,j=void 0!==i.count&&"string"!=typeof i.count,E=o.hasDefaultValue(i),P=j?this.pluralResolver.getSuffix(g,i.count):"",F=i["defaultValue".concat(P)]||i.defaultValue;!this.isValidLookup(v)&&E&&(R=!0,v=F),this.isValidLookup(v)||(C=!0,v=l);var V=E&&F!==v&&this.options.updateMissing;if(C||R||V){if(this.logger.log(V?"updateKey":"missingKey",g,p,l,V?F:v),s){var T=this.resolve(l,n({},i,{keySeparator:!1}));T&&T.res&&this.logger.warn("Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.")}var A=[],U=this.languageUtils.getFallbackCodes(this.options.fallbackLng,i.lng||this.language);if("fallback"===this.options.saveMissingTo&&U&&U[0])for(var I=0;I1&&void 0!==arguments[1]?arguments[1]:{};return"string"==typeof e&&(e=[e]),e.forEach(function(e){if(!a.isValidLookup(t)){var u=a.extractFromKey(e,s),l=u.key;n=l;var c=u.namespaces;a.options.fallbackNS&&(c=c.concat(a.options.fallbackNS));var p=void 0!==s.count&&"string"!=typeof s.count,g=void 0!==s.context&&"string"==typeof s.context&&""!==s.context,f=s.lngs?s.lngs:a.languageUtils.toResolveHierarchy(s.lng||a.language,s.fallbackLng);c.forEach(function(e){a.isValidLookup(t)||(r=e,!N["".concat(f[0],"-").concat(e)]&&a.utils&&a.utils.hasLoadedNamespace&&!a.utils.hasLoadedNamespace(r)&&(N["".concat(f[0],"-").concat(e)]=!0,a.logger.warn('key "'.concat(n,'" for languages "').concat(f.join(", "),'" won\'t get resolved as namespace "').concat(r,'" was not yet loaded'),"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!")),f.forEach(function(n){if(!a.isValidLookup(t)){o=n;var r,u,c=l,f=[c];if(a.i18nFormat&&a.i18nFormat.addLookupKeys)a.i18nFormat.addLookupKeys(f,l,n,e,s);else p&&(r=a.pluralResolver.getSuffix(n,s.count)),p&&g&&f.push(c+r),g&&f.push(c+="".concat(a.options.contextSeparator).concat(s.context)),p&&f.push(c+=r);for(;u=f.pop();)a.isValidLookup(t)||(i=u,t=a.getResource(n,e,u,s))}}))})}}),{res:t,usedKey:n,exactUsedKey:i,usedLng:o,usedNS:r}}},{key:"isValidLookup",value:function(e){return!(void 0===e||!this.options.returnNull&&null===e||!this.options.returnEmptyString&&""===e)}},{key:"getResource",value:function(e,t,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};return this.i18nFormat&&this.i18nFormat.getResource?this.i18nFormat.getResource(e,t,n,i):this.resourceStore.getResource(e,t,n,i)}}],[{key:"hasDefaultValue",value:function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t)&&"defaultValue"===t.substring(0,"defaultValue".length)&&void 0!==e[t])return!0;return!1}}]),o}();function C(e){return e.charAt(0).toUpperCase()+e.slice(1)}var j=function(){function e(t){i(this,e),this.options=t,this.whitelist=this.options.supportedLngs||!1,this.supportedLngs=this.options.supportedLngs||!1,this.logger=g.create("languageUtils")}return r(e,[{key:"getScriptPartFromCode",value:function(e){if(!e||e.indexOf("-")<0)return null;var t=e.split("-");return 2===t.length?null:(t.pop(),"x"===t[t.length-1].toLowerCase()?null:this.formatLanguageCode(t.join("-")))}},{key:"getLanguagePartFromCode",value:function(e){if(!e||e.indexOf("-")<0)return e;var t=e.split("-");return this.formatLanguageCode(t[0])}},{key:"formatLanguageCode",value:function(e){if("string"==typeof e&&e.indexOf("-")>-1){var t=["hans","hant","latn","cyrl","cans","mong","arab"],n=e.split("-");return this.options.lowerCaseLng?n=n.map(function(e){return e.toLowerCase()}):2===n.length?(n[0]=n[0].toLowerCase(),n[1]=n[1].toUpperCase(),t.indexOf(n[1].toLowerCase())>-1&&(n[1]=C(n[1].toLowerCase()))):3===n.length&&(n[0]=n[0].toLowerCase(),2===n[1].length&&(n[1]=n[1].toUpperCase()),"sgn"!==n[0]&&2===n[2].length&&(n[2]=n[2].toUpperCase()),t.indexOf(n[1].toLowerCase())>-1&&(n[1]=C(n[1].toLowerCase())),t.indexOf(n[2].toLowerCase())>-1&&(n[2]=C(n[2].toLowerCase()))),n.join("-")}return this.options.cleanCode||this.options.lowerCaseLng?e.toLowerCase():e}},{key:"isWhitelisted",value:function(e){return this.logger.deprecate("languageUtils.isWhitelisted",'function "isWhitelisted" will be renamed to "isSupportedCode" in the next major - please make sure to rename it\'s usage asap.'),this.isSupportedCode(e)}},{key:"isSupportedCode",value:function(e){return("languageOnly"===this.options.load||this.options.nonExplicitSupportedLngs)&&(e=this.getLanguagePartFromCode(e)),!this.supportedLngs||!this.supportedLngs.length||this.supportedLngs.indexOf(e)>-1}},{key:"getBestMatchFromCodes",value:function(e){var t,n=this;return e?(e.forEach(function(e){if(!t){var i=n.formatLanguageCode(e);n.options.supportedLngs&&!n.isSupportedCode(i)||(t=i)}}),!t&&this.options.supportedLngs&&e.forEach(function(e){if(!t){var i=n.getLanguagePartFromCode(e);if(n.isSupportedCode(i))return t=i;t=n.options.supportedLngs.find(function(e){if(0===e.indexOf(i))return e})}}),t||(t=this.getFallbackCodes(this.options.fallbackLng)[0]),t):null}},{key:"getFallbackCodes",value:function(e,t){if(!e)return[];if("function"==typeof e&&(e=e(t)),"string"==typeof e&&(e=[e]),"[object Array]"===Object.prototype.toString.apply(e))return e;if(!t)return e.default||[];var n=e[t];return n||(n=e[this.getScriptPartFromCode(t)]),n||(n=e[this.formatLanguageCode(t)]),n||(n=e[this.getLanguagePartFromCode(t)]),n||(n=e.default),n||[]}},{key:"toResolveHierarchy",value:function(e,t){var n=this,i=this.getFallbackCodes(t||this.options.fallbackLng||[],e),o=[],r=function(e){e&&(n.isSupportedCode(e)?o.push(e):n.logger.warn("rejecting language code not found in supportedLngs: ".concat(e)))};return"string"==typeof e&&e.indexOf("-")>-1?("languageOnly"!==this.options.load&&r(this.formatLanguageCode(e)),"languageOnly"!==this.options.load&&"currentOnly"!==this.options.load&&r(this.getScriptPartFromCode(e)),"currentOnly"!==this.options.load&&r(this.getLanguagePartFromCode(e))):"string"==typeof e&&r(this.formatLanguageCode(e)),i.forEach(function(e){o.indexOf(e)<0&&r(n.formatLanguageCode(e))}),o}}]),e}(),E=[{lngs:["ach","ak","am","arn","br","fil","gun","ln","mfe","mg","mi","oc","pt","pt-BR","tg","tl","ti","tr","uz","wa"],nr:[1,2],fc:1},{lngs:["af","an","ast","az","bg","bn","ca","da","de","dev","el","en","eo","es","et","eu","fi","fo","fur","fy","gl","gu","ha","hi","hu","hy","ia","it","kk","kn","ku","lb","mai","ml","mn","mr","nah","nap","nb","ne","nl","nn","no","nso","pa","pap","pms","ps","pt-PT","rm","sco","se","si","so","son","sq","sv","sw","ta","te","tk","ur","yo"],nr:[1,2],fc:2},{lngs:["ay","bo","cgg","fa","ht","id","ja","jbo","ka","km","ko","ky","lo","ms","sah","su","th","tt","ug","vi","wo","zh"],nr:[1],fc:3},{lngs:["be","bs","cnr","dz","hr","ru","sr","uk"],nr:[1,2,5],fc:4},{lngs:["ar"],nr:[0,1,2,3,11,100],fc:5},{lngs:["cs","sk"],nr:[1,2,5],fc:6},{lngs:["csb","pl"],nr:[1,2,5],fc:7},{lngs:["cy"],nr:[1,2,3,8],fc:8},{lngs:["fr"],nr:[1,2],fc:9},{lngs:["ga"],nr:[1,2,3,7,11],fc:10},{lngs:["gd"],nr:[1,2,3,20],fc:11},{lngs:["is"],nr:[1,2],fc:12},{lngs:["jv"],nr:[0,1],fc:13},{lngs:["kw"],nr:[1,2,3,4],fc:14},{lngs:["lt"],nr:[1,2,10],fc:15},{lngs:["lv"],nr:[1,2,0],fc:16},{lngs:["mk"],nr:[1,2],fc:17},{lngs:["mnk"],nr:[0,1,2],fc:18},{lngs:["mt"],nr:[1,2,11,20],fc:19},{lngs:["or"],nr:[2,1],fc:2},{lngs:["ro"],nr:[1,2,20],fc:20},{lngs:["sl"],nr:[5,1,2,3],fc:21},{lngs:["he","iw"],nr:[1,2,20,21],fc:22}],P={1:function(e){return Number(e>1)},2:function(e){return Number(1!=e)},3:function(e){return 0},4:function(e){return Number(e%10==1&&e%100!=11?0:e%10>=2&&e%10<=4&&(e%100<10||e%100>=20)?1:2)},5:function(e){return Number(0==e?0:1==e?1:2==e?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5)},6:function(e){return Number(1==e?0:e>=2&&e<=4?1:2)},7:function(e){return Number(1==e?0:e%10>=2&&e%10<=4&&(e%100<10||e%100>=20)?1:2)},8:function(e){return Number(1==e?0:2==e?1:8!=e&&11!=e?2:3)},9:function(e){return Number(e>=2)},10:function(e){return Number(1==e?0:2==e?1:e<7?2:e<11?3:4)},11:function(e){return Number(1==e||11==e?0:2==e||12==e?1:e>2&&e<20?2:3)},12:function(e){return Number(e%10!=1||e%100==11)},13:function(e){return Number(0!==e)},14:function(e){return Number(1==e?0:2==e?1:3==e?2:3)},15:function(e){return Number(e%10==1&&e%100!=11?0:e%10>=2&&(e%100<10||e%100>=20)?1:2)},16:function(e){return Number(e%10==1&&e%100!=11?0:0!==e?1:2)},17:function(e){return Number(1==e||e%10==1&&e%100!=11?0:1)},18:function(e){return Number(0==e?0:1==e?1:2)},19:function(e){return Number(1==e?0:0==e||e%100>1&&e%100<11?1:e%100>10&&e%100<20?2:3)},20:function(e){return Number(1==e?0:0==e||e%100>0&&e%100<20?1:2)},21:function(e){return Number(e%100==1?1:e%100==2?2:e%100==3||e%100==4?3:0)},22:function(e){return Number(1==e?0:2==e?1:(e<0||e>10)&&e%10==0?2:3)}};var F=function(){function e(t){var n,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};i(this,e),this.languageUtils=t,this.options=o,this.logger=g.create("pluralResolver"),this.rules=(n={},E.forEach(function(e){e.lngs.forEach(function(t){n[t]={numbers:e.nr,plurals:P[e.fc]}})}),n)}return r(e,[{key:"addRule",value:function(e,t){this.rules[e]=t}},{key:"getRule",value:function(e){return this.rules[e]||this.rules[this.languageUtils.getLanguagePartFromCode(e)]}},{key:"needsPlural",value:function(e){var t=this.getRule(e);return t&&t.numbers.length>1}},{key:"getPluralFormsOfKey",value:function(e,t){return this.getSuffixes(e).map(function(e){return t+e})}},{key:"getSuffixes",value:function(e){var t=this,n=this.getRule(e);return n?n.numbers.map(function(n){return t.getSuffix(e,n)}):[]}},{key:"getSuffix",value:function(e,t){var n=this,i=this.getRule(e);if(i){var o=i.noAbs?i.plurals(t):i.plurals(Math.abs(t)),r=i.numbers[o];this.options.simplifyPluralSuffix&&2===i.numbers.length&&1===i.numbers[0]&&(2===r?r="plural":1===r&&(r=""));var a=function(){return n.options.prepend&&r.toString()?n.options.prepend+r.toString():r.toString()};return"v1"===this.options.compatibilityJSON?1===r?"":"number"==typeof r?"_plural_".concat(r.toString()):a():"v2"===this.options.compatibilityJSON?a():this.options.simplifyPluralSuffix&&2===i.numbers.length&&1===i.numbers[0]?a():this.options.prepend&&o.toString()?this.options.prepend+o.toString():o.toString()}return this.logger.warn("no plural rule found for: ".concat(e)),""}}]),e}(),V=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};i(this,e),this.logger=g.create("interpolator"),this.options=t,this.format=t.interpolation&&t.interpolation.format||function(e){return e},this.init(t)}return r(e,[{key:"init",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};e.interpolation||(e.interpolation={escapeValue:!0});var t=e.interpolation;this.escape=void 0!==t.escape?t.escape:S,this.escapeValue=void 0===t.escapeValue||t.escapeValue,this.useRawValueToEscape=void 0!==t.useRawValueToEscape&&t.useRawValueToEscape,this.prefix=t.prefix?k(t.prefix):t.prefixEscaped||"{{",this.suffix=t.suffix?k(t.suffix):t.suffixEscaped||"}}",this.formatSeparator=t.formatSeparator?t.formatSeparator:t.formatSeparator||",",this.unescapePrefix=t.unescapeSuffix?"":t.unescapePrefix||"-",this.unescapeSuffix=this.unescapePrefix?"":t.unescapeSuffix||"",this.nestingPrefix=t.nestingPrefix?k(t.nestingPrefix):t.nestingPrefixEscaped||k("$t("),this.nestingSuffix=t.nestingSuffix?k(t.nestingSuffix):t.nestingSuffixEscaped||k(")"),this.nestingOptionsSeparator=t.nestingOptionsSeparator?t.nestingOptionsSeparator:t.nestingOptionsSeparator||",",this.maxReplaces=t.maxReplaces?t.maxReplaces:1e3,this.alwaysFormat=void 0!==t.alwaysFormat&&t.alwaysFormat,this.resetRegExp()}},{key:"reset",value:function(){this.options&&this.init(this.options)}},{key:"resetRegExp",value:function(){var e="".concat(this.prefix,"(.+?)").concat(this.suffix);this.regexp=new RegExp(e,"g");var t="".concat(this.prefix).concat(this.unescapePrefix,"(.+?)").concat(this.unescapeSuffix).concat(this.suffix);this.regexpUnescape=new RegExp(t,"g");var n="".concat(this.nestingPrefix,"(.+?)").concat(this.nestingSuffix);this.nestingRegexp=new RegExp(n,"g")}},{key:"interpolate",value:function(e,t,i,o){var r,a,s,u=this,l=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{};function c(e){return e.replace(/\$/g,"$$$$")}var p=function(e){if(e.indexOf(u.formatSeparator)<0){var r=b(t,l,e);return u.alwaysFormat?u.format(r,void 0,i,n({},o,t,{interpolationkey:e})):r}var a=e.split(u.formatSeparator),s=a.shift().trim(),c=a.join(u.formatSeparator).trim();return u.format(b(t,l,s),c,i,n({},o,t,{interpolationkey:s}))};this.resetRegExp();var g=o&&o.missingInterpolationHandler||this.options.missingInterpolationHandler,f=o&&o.interpolation&&o.interpolation.skipOnVariables||this.options.interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:function(e){return c(e)}},{regex:this.regexp,safeValue:function(e){return u.escapeValue?c(u.escape(e)):c(e)}}].forEach(function(t){for(s=0;r=t.regex.exec(e);){if(void 0===(a=p(r[1].trim())))if("function"==typeof g){var n=g(e,r,o);a="string"==typeof n?n:""}else{if(f){a=r[0];continue}u.logger.warn("missed to pass in variable ".concat(r[1]," for interpolating ").concat(e)),a=""}else"string"==typeof a||u.useRawValueToEscape||(a=d(a));var i=t.safeValue(a);if(e=e.replace(r[0],i),f?(t.regex.lastIndex+=i.length,t.regex.lastIndex-=r[0].length):t.regex.lastIndex=0,++s>=u.maxReplaces)break}}),e}},{key:"nest",value:function(e,t){var i,o,r=this,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},s=n({},a);function u(e,t){var i=this.nestingOptionsSeparator;if(e.indexOf(i)<0)return e;var o=e.split(new RegExp("".concat(i,"[ ]*{"))),r="{".concat(o[1]);e=o[0],r=(r=this.interpolate(r,s)).replace(/'/g,'"');try{s=JSON.parse(r),t&&(s=n({},t,s))}catch(t){return this.logger.warn("failed parsing options string in nesting for key ".concat(e),t),"".concat(e).concat(i).concat(r)}return delete s.defaultValue,e}for(s.applyPostProcessor=!1,delete s.defaultValue;i=this.nestingRegexp.exec(e);){var l=[],c=!1;if(-1!==i[0].indexOf(this.formatSeparator)&&!/{.*}/.test(i[1])){var p=i[1].split(this.formatSeparator).map(function(e){return e.trim()});i[1]=p.shift(),l=p,c=!0}if((o=t(u.call(this,i[1].trim(),s),s))&&i[0]===e&&"string"!=typeof o)return o;"string"!=typeof o&&(o=d(o)),o||(this.logger.warn("missed to resolve ".concat(i[1]," for nesting ").concat(e)),o=""),c&&(o=l.reduce(function(e,t){return r.format(e,t,a.lng,n({},a,{interpolationkey:i[1].trim()}))},o.trim())),e=e.replace(i[0],o),this.regexp.lastIndex=0}return e}}]),e}();var T=function(e){function t(e,n,o){var r,l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};return i(this,t),r=s(this,u(t).call(this)),w&&f.call(a(r)),r.backend=e,r.store=n,r.services=o,r.languageUtils=o.languageUtils,r.options=l,r.logger=g.create("backendConnector"),r.state={},r.queue=[],r.backend&&r.backend.init&&r.backend.init(o,l.backend,l),r}return c(t,f),r(t,[{key:"queueLoad",value:function(e,t,n,i){var o=this,r=[],a=[],s=[],u=[];return e.forEach(function(e){var i=!0;t.forEach(function(t){var s="".concat(e,"|").concat(t);!n.reload&&o.store.hasResourceBundle(e,t)?o.state[s]=2:o.state[s]<0||(1===o.state[s]?a.indexOf(s)<0&&a.push(s):(o.state[s]=1,i=!1,a.indexOf(s)<0&&a.push(s),r.indexOf(s)<0&&r.push(s),u.indexOf(t)<0&&u.push(t)))}),i||s.push(e)}),(r.length||a.length)&&this.queue.push({pending:a,loaded:{},errors:[],callback:i}),{toLoad:r,pending:a,toLoadLanguages:s,toLoadNamespaces:u}}},{key:"loaded",value:function(e,t,n){var i=e.split("|"),o=i[0],r=i[1];t&&this.emit("failedLoading",o,r,t),n&&this.store.addResourceBundle(o,r,n),this.state[e]=t?-1:2;var a={};this.queue.forEach(function(n){var i,s,u,l,c,p;i=n.loaded,s=r,l=v(i,[o],Object),c=l.obj,p=l.k,c[p]=c[p]||[],u&&(c[p]=c[p].concat(s)),u||c[p].push(s),function(e,t){for(var n=e.indexOf(t);-1!==n;)e.splice(n,1),n=e.indexOf(t)}(n.pending,e),t&&n.errors.push(t),0!==n.pending.length||n.done||(Object.keys(n.loaded).forEach(function(e){a[e]||(a[e]=[]),n.loaded[e].length&&n.loaded[e].forEach(function(t){a[e].indexOf(t)<0&&a[e].push(t)})}),n.done=!0,n.errors.length?n.callback(n.errors):n.callback())}),this.emit("loaded",a),this.queue=this.queue.filter(function(e){return!e.done})}},{key:"read",value:function(e,t,n){var i=this,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:350,a=arguments.length>5?arguments[5]:void 0;return e.length?this.backend[n](e,t,function(s,u){s&&u&&o<5?setTimeout(function(){i.read.call(i,e,t,n,o+1,2*r,a)},r):a(s,u)}):a(null,{})}},{key:"prepareLoading",value:function(e,t){var n=this,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},o=arguments.length>3?arguments[3]:void 0;if(!this.backend)return this.logger.warn("No backend was added via i18next.use. Will not load resources."),o&&o();"string"==typeof e&&(e=this.languageUtils.toResolveHierarchy(e)),"string"==typeof t&&(t=[t]);var r=this.queueLoad(e,t,i,o);if(!r.toLoad.length)return r.pending.length||o(),null;r.toLoad.forEach(function(e){n.loadOne(e)})}},{key:"load",value:function(e,t,n){this.prepareLoading(e,t,{},n)}},{key:"reload",value:function(e,t,n){this.prepareLoading(e,t,{reload:!0},n)}},{key:"loadOne",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=e.split("|"),o=i[0],r=i[1];this.read(o,r,"read",void 0,void 0,function(i,a){i&&t.logger.warn("".concat(n,"loading namespace ").concat(r," for language ").concat(o," failed"),i),!i&&a&&t.logger.log("".concat(n,"loaded namespace ").concat(r," for language ").concat(o),a),t.loaded(e,i,a)})}},{key:"saveMissing",value:function(e,t,i,o,r){var a=arguments.length>5&&void 0!==arguments[5]?arguments[5]:{};this.services.utils&&this.services.utils.hasLoadedNamespace&&!this.services.utils.hasLoadedNamespace(t)?this.logger.warn('did not save key "'.concat(i,'" as the namespace "').concat(t,'" was not yet loaded'),"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!"):null!=i&&""!==i&&(this.backend&&this.backend.create&&this.backend.create(e,t,i,o,null,n({},a,{isUpdate:r})),e&&e[0]&&this.store.addResource(e[0],t,i,o))}}]),t}();function A(e){return"string"==typeof e.ns&&(e.ns=[e.ns]),"string"==typeof e.fallbackLng&&(e.fallbackLng=[e.fallbackLng]),"string"==typeof e.fallbackNS&&(e.fallbackNS=[e.fallbackNS]),e.whitelist&&(e.whitelist&&e.whitelist.indexOf("cimode")<0&&(e.whitelist=e.whitelist.concat(["cimode"])),e.supportedLngs=e.whitelist),e.nonExplicitWhitelist&&(e.nonExplicitSupportedLngs=e.nonExplicitWhitelist),e.supportedLngs&&e.supportedLngs.indexOf("cimode")<0&&(e.supportedLngs=e.supportedLngs.concat(["cimode"])),e}function U(){}return new(function(t){function o(){var e,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=arguments.length>1?arguments[1]:void 0;if(i(this,o),e=s(this,u(o).call(this)),w&&f.call(a(e)),e.options=A(t),e.services={},e.logger=g,e.modules={external:[]},n&&!e.isInitialized&&!t.isClone){if(!e.options.initImmediate)return e.init(t,n),s(e,a(e));setTimeout(function(){e.init(t,n)},0)}return e}return c(o,f),r(o,[{key:"init",value:function(){var t=this,i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},o=arguments.length>1?arguments[1]:void 0;function r(e){return e?"function"==typeof e?new e:e:null}if("function"==typeof i&&(o=i,i={}),i.whitelist&&!i.supportedLngs&&this.logger.deprecate("whitelist",'option "whitelist" will be renamed to "supportedLngs" in the next major - please make sure to rename this option asap.'),i.nonExplicitWhitelist&&!i.nonExplicitSupportedLngs&&this.logger.deprecate("whitelist",'options "nonExplicitWhitelist" will be renamed to "nonExplicitSupportedLngs" in the next major - please make sure to rename this option asap.'),this.options=n({},{debug:!1,initImmediate:!0,ns:["translation"],defaultNS:["translation"],fallbackLng:["dev"],fallbackNS:!1,whitelist:!1,nonExplicitWhitelist:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:"all",preload:!1,simplifyPluralSuffix:!0,keySeparator:".",nsSeparator:":",pluralSeparator:"_",contextSeparator:"_",partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:"fallback",saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!0,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:function(t){var n={};if("object"===e(t[1])&&(n=t[1]),"string"==typeof t[1]&&(n.defaultValue=t[1]),"string"==typeof t[2]&&(n.tDescription=t[2]),"object"===e(t[2])||"object"===e(t[3])){var i=t[3]||t[2];Object.keys(i).forEach(function(e){n[e]=i[e]})}return n},interpolation:{escapeValue:!0,format:function(e,t,n,i){return e},prefix:"{{",suffix:"}}",formatSeparator:",",unescapePrefix:"-",nestingPrefix:"$t(",nestingSuffix:")",nestingOptionsSeparator:",",maxReplaces:1e3,skipOnVariables:!1}},this.options,A(i)),this.format=this.options.interpolation.format,o||(o=U),!this.options.isClone){this.modules.logger?g.init(r(this.modules.logger),this.options):g.init(null,this.options);var a=new j(this.options);this.store=new L(this.options.resources,this.options);var s=this.services;s.logger=g,s.resourceStore=this.store,s.languageUtils=a,s.pluralResolver=new F(a,{prepend:this.options.pluralSeparator,compatibilityJSON:this.options.compatibilityJSON,simplifyPluralSuffix:this.options.simplifyPluralSuffix}),s.interpolator=new V(this.options),s.utils={hasLoadedNamespace:this.hasLoadedNamespace.bind(this)},s.backendConnector=new T(r(this.modules.backend),s.resourceStore,s,this.options),s.backendConnector.on("*",function(e){for(var n=arguments.length,i=new Array(n>1?n-1:0),o=1;o1?n-1:0),o=1;o0&&"dev"!==u[0]&&(this.options.lng=u[0])}this.services.languageDetector||this.options.lng||this.logger.warn("init: no languageDetector is used and no lng is defined");["getResource","hasResourceBundle","getResourceBundle","getDataByLanguage"].forEach(function(e){t[e]=function(){var n;return(n=t.store)[e].apply(n,arguments)}});["addResource","addResources","addResourceBundle","removeResourceBundle"].forEach(function(e){t[e]=function(){var n;return(n=t.store)[e].apply(n,arguments),t}});var l=h(),c=function(){var e=function(e,n){t.isInitialized&&t.logger.warn("init: i18next is already initialized. You should call init just once!"),t.isInitialized=!0,t.options.isClone||t.logger.log("initialized",t.options),t.emit("initialized",t.options),l.resolve(n),o(e,n)};if(t.languages&&"v1"!==t.options.compatibilityAPI&&!t.isInitialized)return e(null,t.t.bind(t));t.changeLanguage(t.options.lng,e)};return this.options.resources||!this.options.initImmediate?c():setTimeout(c,0),l}},{key:"loadResources",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:U,i="string"==typeof e?e:this.language;if("function"==typeof e&&(n=e),!this.options.resources||this.options.partialBundledLanguages){if(i&&"cimode"===i.toLowerCase())return n();var o=[],r=function(e){e&&t.services.languageUtils.toResolveHierarchy(e).forEach(function(e){o.indexOf(e)<0&&o.push(e)})};if(i)r(i);else this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(function(e){return r(e)});this.options.preload&&this.options.preload.forEach(function(e){return r(e)}),this.services.backendConnector.load(o,this.options.ns,n)}else n(null)}},{key:"reloadResources",value:function(e,t,n){var i=h();return e||(e=this.languages),t||(t=this.options.ns),n||(n=U),this.services.backendConnector.reload(e,t,function(e){i.resolve(),n(e)}),i}},{key:"use",value:function(e){if(!e)throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");if(!e.type)throw new Error("You are passing a wrong module! Please check the object you are passing to i18next.use()");return"backend"===e.type&&(this.modules.backend=e),("logger"===e.type||e.log&&e.warn&&e.error)&&(this.modules.logger=e),"languageDetector"===e.type&&(this.modules.languageDetector=e),"i18nFormat"===e.type&&(this.modules.i18nFormat=e),"postProcessor"===e.type&&O.addPostProcessor(e),"3rdParty"===e.type&&this.modules.external.push(e),this}},{key:"changeLanguage",value:function(e,t){var n=this;this.isLanguageChangingTo=e;var i=h();this.emit("languageChanging",e);var o=function(e){var o="string"==typeof e?e:n.services.languageUtils.getBestMatchFromCodes(e);o&&(n.language||(n.language=o,n.languages=n.services.languageUtils.toResolveHierarchy(o)),n.translator.language||n.translator.changeLanguage(o),n.services.languageDetector&&n.services.languageDetector.cacheUserLanguage(o)),n.loadResources(o,function(e){!function(e,o){o?(n.language=o,n.languages=n.services.languageUtils.toResolveHierarchy(o),n.translator.changeLanguage(o),n.isLanguageChangingTo=void 0,n.emit("languageChanged",o),n.logger.log("languageChanged",o)):n.isLanguageChangingTo=void 0,i.resolve(function(){return n.t.apply(n,arguments)}),t&&t(e,function(){return n.t.apply(n,arguments)})}(e,o)})};return e||!this.services.languageDetector||this.services.languageDetector.async?!e&&this.services.languageDetector&&this.services.languageDetector.async?this.services.languageDetector.detect(o):o(e):o(this.services.languageDetector.detect()),i}},{key:"getFixedT",value:function(t,i){var o=this,r=function t(i,r){var a;if("object"!==e(r)){for(var s=arguments.length,u=new Array(s>2?s-2:0),l=2;l1&&void 0!==arguments[1]?arguments[1]:{};if(!this.isInitialized)return this.logger.warn("hasLoadedNamespace: i18next was not initialized",this.languages),!1;if(!this.languages||!this.languages.length)return this.logger.warn("hasLoadedNamespace: i18n.languages were undefined or empty",this.languages),!1;var i=this.languages[0],o=!!this.options&&this.options.fallbackLng,r=this.languages[this.languages.length-1];if("cimode"===i.toLowerCase())return!0;var a=function(e,n){var i=t.services.backendConnector.state["".concat(e,"|").concat(n)];return-1===i||2===i};if(n.precheck){var s=n.precheck(this,a);if(void 0!==s)return s}return!!this.hasResourceBundle(i,e)||(!this.services.backendConnector.backend||!(!a(i,e)||o&&!a(r,e)))}},{key:"loadNamespaces",value:function(e,t){var n=this,i=h();return this.options.ns?("string"==typeof e&&(e=[e]),e.forEach(function(e){n.options.ns.indexOf(e)<0&&n.options.ns.push(e)}),this.loadResources(function(e){i.resolve(),t&&t(e)}),i):(t&&t(),Promise.resolve())}},{key:"loadLanguages",value:function(e,t){var n=h();"string"==typeof e&&(e=[e]);var i=this.options.preload||[],o=e.filter(function(e){return i.indexOf(e)<0});return o.length?(this.options.preload=i.concat(o),this.loadResources(function(e){n.resolve(),t&&t(e)}),n):(t&&t(),Promise.resolve())}},{key:"dir",value:function(e){if(e||(e=this.languages&&this.languages.length>0?this.languages[0]:this.language),!e)return"rtl";return["ar","shu","sqr","ssh","xaa","yhd","yud","aao","abh","abv","acm","acq","acw","acx","acy","adf","ads","aeb","aec","afb","ajp","apc","apd","arb","arq","ars","ary","arz","auz","avl","ayh","ayl","ayn","ayp","bbz","pga","he","iw","ps","pbt","pbu","pst","prp","prd","ug","ur","ydd","yds","yih","ji","yi","hbo","men","xmn","fa","jpr","peo","pes","prs","dv","sam"].indexOf(this.services.languageUtils.getLanguagePartFromCode(e))>=0?"rtl":"ltr"}},{key:"createInstance",value:function(){return new o(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},arguments.length>1?arguments[1]:void 0)}},{key:"cloneInstance",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:U,r=n({},this.options,t,{isClone:!0}),a=new o(r);return["store","services","language"].forEach(function(t){a[t]=e[t]}),a.services=n({},this.services),a.services.utils={hasLoadedNamespace:a.hasLoadedNamespace.bind(a)},a.translator=new R(a.services,a.options),a.translator.on("*",function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),i=1;i= 2) {
- console.log('[l10n] ' + message);
- }
- };
-
- function consoleWarn(message) {
- if (gDEBUG) {
- console.warn('[l10n] ' + message);
- }
- };
-
-
- /**
- * DOM helpers for the so-called "HTML API".
- *
- * These functions are written for modern browsers. For old versions of IE,
- * they're overridden in the 'startup' section at the end of this file.
- */
-
- function getL10nResourceLinks() {
- return document.querySelectorAll('link[type="application/l10n"]');
- }
-
- function getL10nDictionary() {
- var script = document.querySelector('script[type="application/l10n"]');
- // TODO: support multiple and external JSON dictionaries
- return script ? JSON.parse(script.innerHTML) : null;
- }
-
- function getTranslatableChildren(element) {
- return element ? element.querySelectorAll('*[data-l10n-id]') : [];
- }
-
- function getL10nAttributes(element) {
- if (!element)
- return {};
-
- var l10nId = element.getAttribute('data-l10n-id');
- var l10nArgs = element.getAttribute('data-l10n-args');
- var args = {};
- if (l10nArgs) {
- try {
- args = JSON.parse(l10nArgs);
- } catch (e) {
- consoleWarn('could not parse arguments for #' + l10nId);
- }
- }
- return { id: l10nId, args: args };
- }
-
- function fireL10nReadyEvent(lang) {
- var evtObject = document.createEvent('Event');
- evtObject.initEvent('localized', true, false);
- evtObject.language = lang;
- document.dispatchEvent(evtObject);
- }
-
- function xhrLoadText(url, onSuccess, onFailure, asynchronous) {
- onSuccess = onSuccess || function _onSuccess(data) {};
- onFailure = onFailure || function _onFailure() {
- consoleWarn(url + ' not found.');
- };
-
- var xhr = new XMLHttpRequest();
- xhr.open('GET', url, asynchronous);
- if (xhr.overrideMimeType) {
- xhr.overrideMimeType('text/plain; charset=utf-8');
- }
- xhr.onreadystatechange = function() {
- if (xhr.readyState == 4) {
- if (xhr.status == 200 || xhr.status === 0) {
- onSuccess(xhr.responseText);
- } else {
- onFailure();
- }
- }
- };
- xhr.onerror = onFailure;
- xhr.ontimeout = onFailure;
-
- // in Firefox OS with the app:// protocol, trying to XHR a non-existing
- // URL will raise an exception here -- hence this ugly try...catch.
- try {
- xhr.send(null);
- } catch (e) {
- onFailure();
- }
- }
-
-
- /**
- * l10n resource parser:
- * - reads (async XHR) the l10n resource matching `lang';
- * - imports linked resources (synchronously) when specified;
- * - parses the text data (fills `gL10nData' and `gTextData');
- * - triggers success/failure callbacks when done.
- *
- * @param {string} href
- * URL of the l10n resource to parse.
- *
- * @param {string} lang
- * locale (language) to parse.
- *
- * @param {Function} successCallback
- * triggered when the l10n resource has been successully parsed.
- *
- * @param {Function} failureCallback
- * triggered when the an error has occured.
- *
- * @return {void}
- * uses the following global variables: gL10nData, gTextData, gTextProp.
- */
-
- function parseResource(href, lang, successCallback, failureCallback) {
- var baseURL = href.replace(/[^\/]*$/, '') || './';
-
- // handle escaped characters (backslashes) in a string
- function evalString(text) {
- if (text.lastIndexOf('\\') < 0)
- return text;
- return text.replace(/\\\\/g, '\\')
- .replace(/\\n/g, '\n')
- .replace(/\\r/g, '\r')
- .replace(/\\t/g, '\t')
- .replace(/\\b/g, '\b')
- .replace(/\\f/g, '\f')
- .replace(/\\{/g, '{')
- .replace(/\\}/g, '}')
- .replace(/\\"/g, '"')
- .replace(/\\'/g, "'");
- }
-
- // parse *.properties text data into an l10n dictionary
- function parseProperties(text) {
- var dictionary = [];
-
- // token expressions
- var reBlank = /^\s*|\s*$/;
- var reComment = /^\s*#|^\s*$/;
- var reSection = /^\s*\[(.*)\]\s*$/;
- var reImport = /^\s*@import\s+url\((.*)\)\s*$/i;
- var reSplit = /^([^=\s]*)\s*=\s*(.+)$/; // TODO: escape EOLs with '\'
-
- // parse the *.properties file into an associative array
- function parseRawLines(rawText, extendedSyntax) {
- var entries = rawText.replace(reBlank, '').split(/[\r\n]+/);
- var currentLang = '*';
- var genericLang = lang.replace(/-[a-z]+$/i, '');
- var skipLang = false;
- var match = '';
-
- for (var i = 0; i < entries.length; i++) {
- var line = entries[i];
-
- // comment or blank line?
- if (reComment.test(line))
- continue;
-
- // the extended syntax supports [lang] sections and @import rules
- if (extendedSyntax) {
- if (reSection.test(line)) { // section start?
- match = reSection.exec(line);
- currentLang = match[1];
- skipLang = (currentLang !== '*') &&
- (currentLang !== lang) && (currentLang !== genericLang);
- continue;
- } else if (skipLang) {
- continue;
- }
- if (reImport.test(line)) { // @import rule?
- match = reImport.exec(line);
- loadImport(baseURL + match[1]); // load the resource synchronously
- }
- }
-
- // key-value pair
- var tmp = line.match(reSplit);
- if (tmp && tmp.length == 3) {
- dictionary[tmp[1]] = evalString(tmp[2]);
- }
- }
- }
-
- // import another *.properties file
- function loadImport(url) {
- xhrLoadText(url, function(content) {
- parseRawLines(content, false); // don't allow recursive imports
- }, null, false); // load synchronously
- }
-
- // fill the dictionary
- parseRawLines(text, true);
- return dictionary;
- }
-
- // load and parse l10n data (warning: global variables are used here)
- xhrLoadText(href, function(response) {
- gTextData += response; // mostly for debug
-
- // parse *.properties text data into an l10n dictionary
- var data = parseProperties(response);
-
- // find attribute descriptions, if any
- for (var key in data) {
- var id, prop, index = key.lastIndexOf('.');
- if (index > 0) { // an attribute has been specified
- id = key.substring(0, index);
- prop = key.substr(index + 1);
- } else { // no attribute: assuming text content by default
- id = key;
- prop = gTextProp;
- }
- if (!gL10nData[id]) {
- gL10nData[id] = {};
- }
- gL10nData[id][prop] = data[key];
- }
-
- // trigger callback
- if (successCallback) {
- successCallback();
- }
- }, failureCallback, gAsyncResourceLoading);
- };
-
- // load and parse all resources for the specified locale
- function loadLocale(lang, callback) {
- callback = callback || function _callback() {};
-
- clear();
- gLanguage = lang;
-
- // check all nodes
- // and load the resource files
- var langLinks = getL10nResourceLinks();
- var langCount = langLinks.length;
- if (langCount == 0) {
- // we might have a pre-compiled dictionary instead
- var dict = getL10nDictionary();
- if (dict && dict.locales && dict.default_locale) {
- consoleLog('using the embedded JSON directory, early way out');
- gL10nData = dict.locales[lang] || dict.locales[dict.default_locale];
- callback();
- } else {
- consoleLog('no resource to load, early way out');
- }
- // early way out
- fireL10nReadyEvent(lang);
- gReadyState = 'complete';
- return;
- }
-
- // start the callback when all resources are loaded
- var onResourceLoaded = null;
- var gResourceCount = 0;
- onResourceLoaded = function() {
- gResourceCount++;
- if (gResourceCount >= langCount) {
- callback();
- fireL10nReadyEvent(lang);
- gReadyState = 'complete';
- }
- };
-
- // load all resource files
- function l10nResourceLink(link) {
- var href = link.href;
- var type = link.type;
- this.load = function(lang, callback) {
- var applied = lang;
- parseResource(href, lang, callback, function() {
- consoleWarn(href + ' not found.');
- applied = '';
- });
- return applied; // return lang if found, an empty string if not found
- };
- }
-
- for (var i = 0; i < langCount; i++) {
- var resource = new l10nResourceLink(langLinks[i]);
- var rv = resource.load(lang, onResourceLoaded);
- if (rv != lang) { // lang not found, used default resource instead
- consoleWarn('"' + lang + '" resource not found');
- gLanguage = '';
- }
- }
- }
-
- // clear all l10n data
- function clear() {
- gL10nData = {};
- gTextData = '';
- gLanguage = '';
- // TODO: clear all non predefined macros.
- // There's no such macro /yet/ but we're planning to have some...
- }
-
-
- /**
- * Get rules for plural forms (shared with JetPack), see:
- * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
- * https://github.com/mozilla/addon-sdk/blob/master/python-lib/plural-rules-generator.p
- *
- * @param {string} lang
- * locale (language) used.
- *
- * @return {Function}
- * returns a function that gives the plural form name for a given integer:
- * var fun = getPluralRules('en');
- * fun(1) -> 'one'
- * fun(0) -> 'other'
- * fun(1000) -> 'other'.
- */
-
- function getPluralRules(lang) {
- var locales2rules = {
- 'af': 3,
- 'ak': 4,
- 'am': 4,
- 'ar': 1,
- 'asa': 3,
- 'az': 0,
- 'be': 11,
- 'bem': 3,
- 'bez': 3,
- 'bg': 3,
- 'bh': 4,
- 'bm': 0,
- 'bn': 3,
- 'bo': 0,
- 'br': 20,
- 'brx': 3,
- 'bs': 11,
- 'ca': 3,
- 'cgg': 3,
- 'chr': 3,
- 'cs': 12,
- 'cy': 17,
- 'da': 3,
- 'de': 3,
- 'dv': 3,
- 'dz': 0,
- 'ee': 3,
- 'el': 3,
- 'en': 3,
- 'eo': 3,
- 'es': 3,
- 'et': 3,
- 'eu': 3,
- 'fa': 0,
- 'ff': 5,
- 'fi': 3,
- 'fil': 4,
- 'fo': 3,
- 'fr': 5,
- 'fur': 3,
- 'fy': 3,
- 'ga': 8,
- 'gd': 24,
- 'gl': 3,
- 'gsw': 3,
- 'gu': 3,
- 'guw': 4,
- 'gv': 23,
- 'ha': 3,
- 'haw': 3,
- 'he': 2,
- 'hi': 4,
- 'hr': 11,
- 'hu': 0,
- 'id': 0,
- 'ig': 0,
- 'ii': 0,
- 'is': 3,
- 'it': 3,
- 'iu': 7,
- 'ja': 0,
- 'jmc': 3,
- 'jv': 0,
- 'ka': 0,
- 'kab': 5,
- 'kaj': 3,
- 'kcg': 3,
- 'kde': 0,
- 'kea': 0,
- 'kk': 3,
- 'kl': 3,
- 'km': 0,
- 'kn': 0,
- 'ko': 0,
- 'ksb': 3,
- 'ksh': 21,
- 'ku': 3,
- 'kw': 7,
- 'lag': 18,
- 'lb': 3,
- 'lg': 3,
- 'ln': 4,
- 'lo': 0,
- 'lt': 10,
- 'lv': 6,
- 'mas': 3,
- 'mg': 4,
- 'mk': 16,
- 'ml': 3,
- 'mn': 3,
- 'mo': 9,
- 'mr': 3,
- 'ms': 0,
- 'mt': 15,
- 'my': 0,
- 'nah': 3,
- 'naq': 7,
- 'nb': 3,
- 'nd': 3,
- 'ne': 3,
- 'nl': 3,
- 'nn': 3,
- 'no': 3,
- 'nr': 3,
- 'nso': 4,
- 'ny': 3,
- 'nyn': 3,
- 'om': 3,
- 'or': 3,
- 'pa': 3,
- 'pap': 3,
- 'pl': 13,
- 'ps': 3,
- 'pt': 3,
- 'rm': 3,
- 'ro': 9,
- 'rof': 3,
- 'ru': 11,
- 'rwk': 3,
- 'sah': 0,
- 'saq': 3,
- 'se': 7,
- 'seh': 3,
- 'ses': 0,
- 'sg': 0,
- 'sh': 11,
- 'shi': 19,
- 'sk': 12,
- 'sl': 14,
- 'sma': 7,
- 'smi': 7,
- 'smj': 7,
- 'smn': 7,
- 'sms': 7,
- 'sn': 3,
- 'so': 3,
- 'sq': 3,
- 'sr': 11,
- 'ss': 3,
- 'ssy': 3,
- 'st': 3,
- 'sv': 3,
- 'sw': 3,
- 'syr': 3,
- 'ta': 3,
- 'te': 3,
- 'teo': 3,
- 'th': 0,
- 'ti': 4,
- 'tig': 3,
- 'tk': 3,
- 'tl': 4,
- 'tn': 3,
- 'to': 0,
- 'tr': 0,
- 'ts': 3,
- 'tzm': 22,
- 'uk': 11,
- 'ur': 3,
- 've': 3,
- 'vi': 0,
- 'vun': 3,
- 'wa': 4,
- 'wae': 3,
- 'wo': 0,
- 'xh': 3,
- 'xog': 3,
- 'yo': 0,
- 'zh': 0,
- 'zu': 3
- };
-
- // utility functions for plural rules methods
- function isIn(n, list) {
- return list.indexOf(n) !== -1;
- }
- function isBetween(n, start, end) {
- return start <= n && n <= end;
- }
-
- // list of all plural rules methods:
- // map an integer to the plural form name to use
- var pluralRules = {
- '0': function(n) {
- return 'other';
- },
- '1': function(n) {
- if ((isBetween((n % 100), 3, 10)))
- return 'few';
- if (n === 0)
- return 'zero';
- if ((isBetween((n % 100), 11, 99)))
- return 'many';
- if (n == 2)
- return 'two';
- if (n == 1)
- return 'one';
- return 'other';
- },
- '2': function(n) {
- if (n !== 0 && (n % 10) === 0)
- return 'many';
- if (n == 2)
- return 'two';
- if (n == 1)
- return 'one';
- return 'other';
- },
- '3': function(n) {
- if (n == 1)
- return 'one';
- return 'other';
- },
- '4': function(n) {
- if ((isBetween(n, 0, 1)))
- return 'one';
- return 'other';
- },
- '5': function(n) {
- if ((isBetween(n, 0, 2)) && n != 2)
- return 'one';
- return 'other';
- },
- '6': function(n) {
- if (n === 0)
- return 'zero';
- if ((n % 10) == 1 && (n % 100) != 11)
- return 'one';
- return 'other';
- },
- '7': function(n) {
- if (n == 2)
- return 'two';
- if (n == 1)
- return 'one';
- return 'other';
- },
- '8': function(n) {
- if ((isBetween(n, 3, 6)))
- return 'few';
- if ((isBetween(n, 7, 10)))
- return 'many';
- if (n == 2)
- return 'two';
- if (n == 1)
- return 'one';
- return 'other';
- },
- '9': function(n) {
- if (n === 0 || n != 1 && (isBetween((n % 100), 1, 19)))
- return 'few';
- if (n == 1)
- return 'one';
- return 'other';
- },
- '10': function(n) {
- if ((isBetween((n % 10), 2, 9)) && !(isBetween((n % 100), 11, 19)))
- return 'few';
- if ((n % 10) == 1 && !(isBetween((n % 100), 11, 19)))
- return 'one';
- return 'other';
- },
- '11': function(n) {
- if ((isBetween((n % 10), 2, 4)) && !(isBetween((n % 100), 12, 14)))
- return 'few';
- if ((n % 10) === 0 ||
- (isBetween((n % 10), 5, 9)) ||
- (isBetween((n % 100), 11, 14)))
- return 'many';
- if ((n % 10) == 1 && (n % 100) != 11)
- return 'one';
- return 'other';
- },
- '12': function(n) {
- if ((isBetween(n, 2, 4)))
- return 'few';
- if (n == 1)
- return 'one';
- return 'other';
- },
- '13': function(n) {
- if ((isBetween((n % 10), 2, 4)) && !(isBetween((n % 100), 12, 14)))
- return 'few';
- if (n != 1 && (isBetween((n % 10), 0, 1)) ||
- (isBetween((n % 10), 5, 9)) ||
- (isBetween((n % 100), 12, 14)))
- return 'many';
- if (n == 1)
- return 'one';
- return 'other';
- },
- '14': function(n) {
- if ((isBetween((n % 100), 3, 4)))
- return 'few';
- if ((n % 100) == 2)
- return 'two';
- if ((n % 100) == 1)
- return 'one';
- return 'other';
- },
- '15': function(n) {
- if (n === 0 || (isBetween((n % 100), 2, 10)))
- return 'few';
- if ((isBetween((n % 100), 11, 19)))
- return 'many';
- if (n == 1)
- return 'one';
- return 'other';
- },
- '16': function(n) {
- if ((n % 10) == 1 && n != 11)
- return 'one';
- return 'other';
- },
- '17': function(n) {
- if (n == 3)
- return 'few';
- if (n === 0)
- return 'zero';
- if (n == 6)
- return 'many';
- if (n == 2)
- return 'two';
- if (n == 1)
- return 'one';
- return 'other';
- },
- '18': function(n) {
- if (n === 0)
- return 'zero';
- if ((isBetween(n, 0, 2)) && n !== 0 && n != 2)
- return 'one';
- return 'other';
- },
- '19': function(n) {
- if ((isBetween(n, 2, 10)))
- return 'few';
- if ((isBetween(n, 0, 1)))
- return 'one';
- return 'other';
- },
- '20': function(n) {
- if ((isBetween((n % 10), 3, 4) || ((n % 10) == 9)) && !(
- isBetween((n % 100), 10, 19) ||
- isBetween((n % 100), 70, 79) ||
- isBetween((n % 100), 90, 99)
- ))
- return 'few';
- if ((n % 1000000) === 0 && n !== 0)
- return 'many';
- if ((n % 10) == 2 && !isIn((n % 100), [12, 72, 92]))
- return 'two';
- if ((n % 10) == 1 && !isIn((n % 100), [11, 71, 91]))
- return 'one';
- return 'other';
- },
- '21': function(n) {
- if (n === 0)
- return 'zero';
- if (n == 1)
- return 'one';
- return 'other';
- },
- '22': function(n) {
- if ((isBetween(n, 0, 1)) || (isBetween(n, 11, 99)))
- return 'one';
- return 'other';
- },
- '23': function(n) {
- if ((isBetween((n % 10), 1, 2)) || (n % 20) === 0)
- return 'one';
- return 'other';
- },
- '24': function(n) {
- if ((isBetween(n, 3, 10) || isBetween(n, 13, 19)))
- return 'few';
- if (isIn(n, [2, 12]))
- return 'two';
- if (isIn(n, [1, 11]))
- return 'one';
- return 'other';
- }
- };
-
- // return a function that gives the plural form name for a given integer
- var index = locales2rules[lang.replace(/-.*$/, '')];
- if (!(index in pluralRules)) {
- consoleWarn('plural form unknown for [' + lang + ']');
- return function() { return 'other'; };
- }
- return pluralRules[index];
- }
-
- // pre-defined 'plural' macro
- gMacros.plural = function(str, param, key, prop) {
- var n = parseFloat(param);
- if (isNaN(n))
- return str;
-
- // TODO: support other properties (l20n still doesn't...)
- if (prop != gTextProp)
- return str;
-
- // initialize _pluralRules
- if (!gMacros._pluralRules) {
- gMacros._pluralRules = getPluralRules(gLanguage);
- }
- var index = '[' + gMacros._pluralRules(n) + ']';
-
- // try to find a [zero|one|two] key if it's defined
- if (n === 0 && (key + '[zero]') in gL10nData) {
- str = gL10nData[key + '[zero]'][prop];
- } else if (n == 1 && (key + '[one]') in gL10nData) {
- str = gL10nData[key + '[one]'][prop];
- } else if (n == 2 && (key + '[two]') in gL10nData) {
- str = gL10nData[key + '[two]'][prop];
- } else if ((key + index) in gL10nData) {
- str = gL10nData[key + index][prop];
- } else if ((key + '[other]') in gL10nData) {
- str = gL10nData[key + '[other]'][prop];
- }
-
- return str;
- };
-
-
- /**
- * l10n dictionary functions
- */
-
- // fetch an l10n object, warn if not found, apply `args' if possible
- function getL10nData(key, args) {
- var data = gL10nData[key];
- if (!data) {
- consoleWarn('#' + key + ' missing for [' + gLanguage + ']');
- }
-
- /** This is where l10n expressions should be processed.
- * The plan is to support C-style expressions from the l20n project;
- * until then, only two kinds of simple expressions are supported:
- * {[ index ]} and {{ arguments }}.
- */
- var rv = {};
- for (var prop in data) {
- var str = data[prop];
- str = substIndexes(str, args, key, prop);
- str = substArguments(str, args);
- rv[prop] = str;
- }
- return rv;
- }
-
- // replace {[macros]} with their values
- function substIndexes(str, args, key, prop) {
- var reIndex = /\{\[\s*([a-zA-Z]+)\(([a-zA-Z]+)\)\s*\]\}/;
- var reMatch = reIndex.exec(str);
- if (!reMatch || !reMatch.length)
- return str;
-
- // an index/macro has been found
- // Note: at the moment, only one parameter is supported
- var macroName = reMatch[1];
- var paramName = reMatch[2];
- var param;
- if (args && paramName in args) {
- param = args[paramName];
- } else if (paramName in gL10nData) {
- param = gL10nData[paramName];
- }
-
- // there's no macro parser yet: it has to be defined in gMacros
- if (macroName in gMacros) {
- var macro = gMacros[macroName];
- str = macro(str, param, key, prop);
- }
- return str;
- }
-
- // replace {{arguments}} with their values
- function substArguments(str, args) {
- var reArgs = /\{\{\s*([a-zA-Z\.]+)\s*\}\}/;
- var match = reArgs.exec(str);
- while (match) {
- if (!match || match.length < 2)
- return str; // argument key not found
-
- var arg = match[1];
- var sub = '';
- if (arg in args) {
- sub = args[arg];
- } else if (arg in gL10nData) {
- sub = gL10nData[arg][gTextProp];
- } else {
- consoleWarn('could not find argument {{' + arg + '}}');
- return str;
- }
-
- str = str.substring(0, match.index) + sub +
- str.substr(match.index + match[0].length);
- match = reArgs.exec(str);
- }
- return str;
- }
-
- // translate an HTML element
- function translateElement(element) {
- var l10n = getL10nAttributes(element);
- if (!l10n.id)
- return;
-
- // get the related l10n object
- var data = getL10nData(l10n.id, l10n.args);
- if (!data) {
- consoleWarn('#' + l10n.id + ' missing for [' + gLanguage + ']');
- return;
- }
-
- // translate element (TODO: security checks?)
- // for the node content, replace the content of the first child textNode
- // and clear other child textNodes
- if (data[gTextProp]) { // XXX
- if (getChildElementCount(element) === 0) {
- element[gTextProp] = data[gTextProp];
- } else {
- var children = element.childNodes,
- found = false;
- for (var i = 0, l = children.length; i < l; i++) {
- if (children[i].nodeType === 3 &&
- /\S/.test(children[i].textContent)) { // XXX
- // using nodeValue seems cross-browser
- if (found) {
- children[i].nodeValue = '';
- } else {
- children[i].nodeValue = data[gTextProp];
- found = true;
- }
- }
- }
- if (!found) {
- consoleWarn('unexpected error, could not translate element content');
- }
- }
- delete data[gTextProp];
- }
-
- for (var k in data) {
- element[k] = data[k];
- }
- }
-
- // webkit browsers don't currently support 'children' on SVG elements...
- function getChildElementCount(element) {
- if (element.children) {
- return element.children.length;
- }
- if (typeof element.childElementCount !== 'undefined') {
- return element.childElementCount;
- }
- var count = 0;
- for (var i = 0; i < element.childNodes.length; i++) {
- count += element.nodeType === 1 ? 1 : 0;
- }
- return count;
- }
-
- // translate an HTML subtree
- function translateFragment(element) {
- element = element || document.documentElement;
-
- // check all translatable children (= w/ a `data-l10n-id' attribute)
- var children = getTranslatableChildren(element);
- var elementCount = children.length;
- for (var i = 0; i < elementCount; i++) {
- translateElement(children[i]);
- }
-
- // translate element itself if necessary
- translateElement(element);
- }
-
- // Startup & Public API
-
- function l10nStartup() {
- gReadyState = 'interactive';
- consoleLog('loading [' + navigator.language + '] resources, ' +
- (gAsyncResourceLoading ? 'asynchronously.' : 'synchronously.'));
-
- // load the default locale and translate the document if required
- if (document.documentElement.lang === navigator.language) {
- loadLocale(navigator.language);
- } else {
- loadLocale(navigator.language, translateFragment);
- }
- }
-
- // public API
- var l10n = {
- start: function() {
- if (document.readyState === 'complete' ||
- document.readyState === 'interactive') {
- window.setTimeout(l10nStartup);
- } else {
- document.addEventListener('DOMContentLoaded', l10nStartup);
- }
- },
-
- // get a localized string
- get: function l10n_get(key, args, fallback) {
- var data = getL10nData(key, args) || fallback;
- if (data) {
- return 'textContent' in data ? data.textContent : '';
- }
- return '{{' + key + '}}';
- },
-
- // get|set the document language and direction
- get language() {
- return {
- // get|set the document language (ISO-639-1)
- get code() { return gLanguage; },
- set code(lang) { loadLocale(lang, translateFragment); },
-
- // get the direction (ltr|rtl) of the current language
- get direction() {
- // http://www.w3.org/International/questions/qa-scripts
- // Arabic, Hebrew, Farsi, Pashto, Urdu
- var rtlList = ['ar', 'he', 'fa', 'ps', 'ur'];
- return (rtlList.indexOf(gLanguage) >= 0) ? 'rtl' : 'ltr';
- }
- };
- },
-
- // translate an element or document fragment
- translate: translateFragment,
-
- // get (a clone of) the dictionary for the current locale
- get dictionary() { return JSON.parse(JSON.stringify(gL10nData)); },
-
- // this can be used to prevent race conditions
- get readyState() { return gReadyState; },
- ready: function l10n_ready(callback) {
- if (!callback)
- return;
-
- if (gReadyState == 'complete') {
- window.setTimeout(callback);
- } else {
- window.addEventListener('localized', callback);
- }
- }
- };
-
- return l10n;
-});
diff --git a/activities/FractionBounce.activity/locale.ini b/activities/FractionBounce.activity/locale.ini
deleted file mode 100644
index 9cca3a1bf..000000000
--- a/activities/FractionBounce.activity/locale.ini
+++ /dev/null
@@ -1,183 +0,0 @@
-[*]
-FractionBounceActivity=Fraction Activity
-Help=Help
-Undo=Undo
-Fullscreen=Fullscreen
-Level=Level
-Settings=Settings
-Ball=Ball
-Bg=Background
-Fractions=Fractions
-Sectors=Sectors
-Percents=Percents
-TutoPrev=Prev
-TutoNext=Next
-TutoEnd=End
-Template=Templates
-HelpClickToStart=Click on play to start. Use arrow keys or click to move the ball
-HelpBounceToPosition=Bounce the ball to a position
-HelpOfTheWay=of the way from the left side of the bar
-HelpGameOver=Game Over. Press the play button to start again
-TutoTitle=Fraction activity
-TutoContent=Welcome to the Fraction activity. This is a game that prompts the player to nudge a bouncing ball to land at a point on the bottom of the screen that is an estimate of a given fraction
-TutoBallTitle=Ball
-TutoBallContent=Click on the ball to start the game. A fraction/percentage will be shown on top of the ball signifying the fraction to land on
-TutoBallControlsTitle=Ball Controls
-TutoBallControlsContent=Use left and right arrow keys to control the ball. You can also control the ball using mouse by clicking to the left or right of the ball or by tilting your device
-TutoSlopeTitle=Slope
-TutoSlopeContent=The slope shows the various divisions for the interval 0 to 1 (or 0 to 100%). You will have to bounce the ball somewhere on the slope at the specified fraction distance from the left
-TutoLogTitle=Log
-TutoLogContent=This section will show a table of answers made by the user
-TutoPlayTitle=Play/Pause
-TutoPlayContent=Use this button to play or pause your game
-TutoSettingsTitle=Settings
-TutoSettingsContent=Custom fractions can be added here. These fractions will be added to the random list of fractions proposed to the user
-TutoBallSelectTitle=Ball Style
-TutoBallSelectContent=The ball can be chosen from one of the presets or an image from the journal
-TutoBgSelectTitle=Background Style
-TutoBgSelectContent=The background can be chosen from one of the presets or an image from the journal
-TutoFractionsModeTitle=Fraction Mode
-TutoFractionsModeContent=In this mode, fraction will be displayed over the ball
-TutoSectorsModeTitle=Sectors Mode
-TutoSectorsModeContent=In this mode, sectors of a circle denoting the fraction will be displayed over the ball
-TutoPercentsModeTitle=Percents Mode
-TutoPercentsModeContent=In this mode, percentage denoting the fraction will be displayed over the ball
-Score=score :
-
-[en]
-FractionBounceActivity=Fraction Activity
-Help=Help
-Undo=Undo
-Fullscreen=Fullscreen
-Level=Level
-Settings=Settings
-Ball=Ball
-Bg=Background
-Fractions=Fractions
-Sectors=Sectors
-Percents=Percents
-TutoPrev=Prev
-TutoNext=Next
-TutoEnd=End
-Template=Templates
-HelpClickToStart=Click on play to start. Use arrow keys or click to move the ball
-HelpBounceToPosition=Bounce the ball to a position
-HelpOfTheWay=of the way from the left side of the bar
-HelpGameOver=Game Over. Press the play button to start again
-TutoTitle=Fraction activity
-TutoContent=Welcome to the Fraction activity. This is a game that prompts the player to nudge a bouncing ball to land at a point on the bottom of the screen that is an estimate of a given fraction
-TutoBallTitle=Ball
-TutoBallContent=Click on the ball to start the game. A fraction/percentage will be shown on top of the ball signifying the fraction to land on
-TutoBallControlsTitle=Ball Controls
-TutoBallControlsContent=Use left and right arrow keys to control the ball. You can also control the ball using mouse by clicking to the left or right of the ball or by tilting your device
-TutoSlopeTitle=Slope
-TutoSlopeContent=The slope shows the various divisions for the interval 0 to 1 (or 0 to 100%). You will have to bounce the ball somewhere on the slope at the specified fraction distance from the left
-TutoLogTitle=Log
-TutoLogContent=This section will show a table of answers made by the user
-TutoPlayTitle=Play/Pause
-TutoPlayContent=Use this button to play or pause your game
-TutoSettingsTitle=Settings
-TutoSettingsContent=Custom fractions can be added here. These fractions will be added to the random list of fractions proposed to the user
-TutoBallSelectTitle=Ball Style
-TutoBallSelectContent=The ball can be chosen from one of the presets or an image from the journal
-TutoBgSelectTitle=Background Style
-TutoBgSelectContent=The background can be chosen from one of the presets or an image from the journal
-TutoFractionsModeTitle=Fraction Mode
-TutoFractionsModeContent=In this mode, fraction will be displayed over the ball
-TutoSectorsModeTitle=Sectors Mode
-TutoSectorsModeContent=In this mode, sectors of a circle denoting the fraction will be displayed over the ball
-TutoPercentsModeTitle=Percents Mode
-TutoPercentsModeContent=In this mode, percentage denoting the fraction will be displayed over the ball
-Score=score :
-
-[es]
-FractionBounceActivity=Actividad "Fracción"
-Help=Ayuda
-Undo=Deshacer
-Fullscreen=Pantalla completa
-Level=Level
-Settings=Ajustes
-Ball=Pelota
-Bg=Fondo
-Fractions=Fracciones
-Sectors=Sectores
-Percents=Porcentajes
-TutoPrev=Ant
-TutoNext=Sig
-TutoEnd=Fin
-Template=Plantillas
-HelpClickToStart=Haz clic en "Jugar" para iniciar el juego. Usa las teclas de dirección o haz clic para mover la pelota
-HelpBounceToPosition=Haz que la pelota rebote a un lugar
-HelpOfTheWay=del camino desde la parte izquierda de la barra
-HelpGameOver=Fin del juego. Pulsa el botón "Jugar" para iniciar otra partida
-TutoTitle=Actividad "Fracción"
-TutoContent=Bienvenido a la actividad "Fracción". En este juego, el alumno debe desplazar una pelota haciendo que bote sobre un punto de la parte inferior de la pantalla, que vendrá marcado con el valor estimado de una fracción dada
-TutoBallTitle=Pelota
-TutoBallContent=Haz clic en la pelota para iniciar la partida. Se mostrará una fracción/porcentaje encima de la pelota, que es la fracción en la que debes rebotarla
-TutoBallControlsTitle=Controles de la pelota
-TutoBallControlsContent=Usa las teclas de dirección izquierda y derecha para controlar la pelota. También podrás controlarla usando el ratón y haciendo clic a la izquierda o derecha de la misma. Por último, también podrás inclinar tu dispositivo
-TutoSlopeTitle=Pendiente
-TutoSlopeContent=La pendiente muestra las diferentes divisiones que tiene el intervalo entre 0 y 1 (o desde el 0 hasta el 100 %). Tendrás que hacer que la pelota bote en un punto de la pendiente donde esté la fracción definida a la izquierda de la pantalla
-TutoLogTitle=Registro
-TutoLogContent=En esta sección se muestra una tabla de respuestas del usuario
-TutoPlayTitle=Jugar/Pausar
-TutoPlayContent=Usa este botón para jugar o pausar tu partida
-TutoSettingsTitle=Ajustes
-TutoSettingsContent=Podrás añadir fracciones personalizadas en este menú. Las fracciones que definas aquí se añadirán a la lista de fracciones aleatorias que pueden usarse para crear una partida
-TutoBallSelectTitle=Estilo de la pelota
-TutoBallSelectContent=Se puede escoger la apariencia de la pelota de entre un grupo de temas predefinidos o usando una imagen de tu biblioteca
-TutoBgSelectTitle=Estilo de fondo
-TutoBgSelectContent=Podrás escoger el fondo de pantalla de entre un grupo predefinido de temas o de una imagen de tu biblioteca
-TutoFractionsModeTitle=Modo "Fracción"
-TutoFractionsModeContent=En este modo, se mostrará la fracción sobre la pelota
-TutoSectorsModeTitle=Modo "Sectores"
-TutoSectorsModeContent=En este modo, se mostrará la fracción sobre la pelota en forma de círculo con sectores
-TutoPercentsModeTitle=Modo "Porcentaje"
-TutoPercentsModeContent=En este modo, se mostrará la fracción sobre la pelota en forma de porcentaje
-Score=puntaje :
-
-[fr]
-FractionBounceActivity=Activité Fraction
-Help=Aide
-Undo=Annuler
-Fullscreen=Plein écran
-Level=Niveau
-Settings=Paramètrage
-Ball=Balle
-Bg=Fond d'écran
-Fractions=Fractions
-Sectors=Secteurs
-Percents=Pourcentages
-TutoPrev=Préc
-TutoNext=Suiv
-TutoEnd=Fin
-Template=Modèles
-HelpClickToStart=Play pour démarrer. Clic ou flèches pour déplacer balle
-HelpBounceToPosition=Rebondir à
-HelpOfTheWay=du bas de la pente
-HelpGameOver=Fini ! Play pour redémarrer
-TutoTitle=Activité Fraction
-TutoContent=Bienvenue dans l'activité Franction. Fraction est un jeu où il faut déplacer une balle rebondissante pour qu'elle rebondisse à l'endroit de la fraction
-TutoBallTitle=Balle
-TutoBallContent=Cliquez sur la balle pour démarrer. Une fraction ou un pourcentage sera affiché au dessus de la balle. C'est l'endroit où il faudra la faire atterrir
-TutoBallControlsTitle=Contrôle Balle
-TutoBallControlsContent=Utilisez les flèches du clavier pour contrôler la balle. Vous pouvez aussi la contrôler en cliquant à sa gauche ou à sa droite ou en penchant votre machine
-TutoSlopeTitle=Pente
-TutoSlopeContent=La pente affiche les différentes divisions dans l'intervalle 0 à 1 (ou 0 à 100%). Vous devez faire rebondir la balle sur la pente à l'endroit correspondant à la distance de la fraction depuis la gauche
-TutoLogTitle=Journal
-TutoLogContent=Cette section affiche une table avec les réponses qui ont été données
-TutoPlayTitle=Play/Pause
-TutoPlayContent=Utilisez ce bouton pour lancer ou mettre en pause le jeu
-TutoSettingsTitle=Paramètrage
-TutoSettingsContent=Ici vous pouvez ajouter des fractions. Ces fractions seront ajoutées à la liste des fractions qui peuvent être proposées à l'utilisateur
-TutoBallSelectTitle=Style Balle
-TutoBallSelectContent=Le style de la balle peut être choisi parmi une liste ou en utilisant une image du Journal
-TutoBgSelectTitle=Style Fond
-TutoBgSelectContent=Le fond d'écran peut être choisi parmi une liste ou en utilisant une image du Journal
-TutoFractionsModeTitle=Mode Fraction
-TutoFractionsModeContent=Dans ce mode, des fractions seront affichés sur la balle
-TutoSectorsModeTitle=Mode Secteur
-TutoSectorsModeContent=Dans ce mode, le secteur correspondant à la fraction à trouver est affiché au dessus de la balle
-TutoPercentsModeTitle=Mode Pourcentage
-TutoPercentsModeContent=Dans ce mode, le pourcentage correspondant à la fraction est affiché au dessus de la balle
-Score=score :
diff --git a/activities/FractionBounce.activity/locales/en.json b/activities/FractionBounce.activity/locales/en.json
new file mode 100644
index 000000000..f56b2eb37
--- /dev/null
+++ b/activities/FractionBounce.activity/locales/en.json
@@ -0,0 +1,46 @@
+{
+ "FractionBounceActivity": "Fraction Activity",
+ "Help": "Help",
+ "Undo": "Undo",
+ "Fullscreen": "Fullscreen",
+ "Level": "Level",
+ "Settings": "Settings",
+ "Ball": "Ball",
+ "Bg": "Background",
+ "Fractions": "Fractions",
+ "Sectors": "Sectors",
+ "Percents": "Percents",
+ "TutoPrev": "Prev",
+ "TutoNext": "Next",
+ "TutoEnd": "End",
+ "Template": "Templates",
+ "HelpClickToStart": "Click on play to start. Use arrow keys or click to move the ball",
+ "HelpBounceToPosition": "Bounce the ball to a position",
+ "HelpOfTheWay": "of the way from the left side of the bar",
+ "HelpGameOver": "Game Over. Press the play button to start again",
+ "TutoTitle": "Fraction activity",
+ "TutoContent": "Welcome to the Fraction activity. This is a game that prompts the player to nudge a bouncing ball to land at a point on the bottom of the screen that is an estimate of a given fraction",
+ "TutoBallTitle": "Ball",
+ "TutoBallContent": "Click on the ball to start the game. A fraction/percentage will be shown on top of the ball signifying the fraction to land on",
+ "TutoBallControlsTitle": "Ball Controls",
+ "TutoBallControlsContent": "Use left and right arrow keys to control the ball. You can also control the ball using mouse by clicking to the left or right of the ball or by tilting your device",
+ "TutoSlopeTitle": "Slope",
+ "TutoSlopeContent": "The slope shows the various divisions for the interval 0 to 1 (or 0 to 100%). You will have to bounce the ball somewhere on the slope at the specified fraction distance from the left",
+ "TutoLogTitle": "Log",
+ "TutoLogContent": "This section will show a table of answers made by the user",
+ "TutoPlayTitle": "Play/Pause",
+ "TutoPlayContent": "Use this button to play or pause your game",
+ "TutoSettingsTitle": "Settings",
+ "TutoSettingsContent": "Custom fractions can be added here. These fractions will be added to the random list of fractions proposed to the user",
+ "TutoBallSelectTitle": "Ball Style",
+ "TutoBallSelectContent": "The ball can be chosen from one of the presets or an image from the journal",
+ "TutoBgSelectTitle": "Background Style",
+ "TutoBgSelectContent": "The background can be chosen from one of the presets or an image from the journal",
+ "TutoFractionsModeTitle": "Fraction Mode",
+ "TutoFractionsModeContent": "In this mode, fraction will be displayed over the ball",
+ "TutoSectorsModeTitle": "Sectors Mode",
+ "TutoSectorsModeContent": "In this mode, sectors of a circle denoting the fraction will be displayed over the ball",
+ "TutoPercentsModeTitle": "Percents Mode",
+ "TutoPercentsModeContent": "In this mode, percentage denoting the fraction will be displayed over the ball",
+ "Score": "score :"
+}
diff --git a/activities/FractionBounce.activity/locales/es.json b/activities/FractionBounce.activity/locales/es.json
new file mode 100644
index 000000000..5a62812d0
--- /dev/null
+++ b/activities/FractionBounce.activity/locales/es.json
@@ -0,0 +1,46 @@
+{
+ "FractionBounceActivity": "Actividad \"Fracción\"",
+ "Help": "Ayuda",
+ "Undo": "Deshacer",
+ "Fullscreen": "Pantalla completa",
+ "Level": "Level",
+ "Settings": "Ajustes",
+ "Ball": "Pelota",
+ "Bg": "Fondo",
+ "Fractions": "Fracciones",
+ "Sectors": "Sectores",
+ "Percents": "Porcentajes",
+ "TutoPrev": "Ant",
+ "TutoNext": "Sig",
+ "TutoEnd": "Fin",
+ "Template": "Plantillas",
+ "HelpClickToStart": "Haz clic en \"Jugar\" para iniciar el juego. Usa las teclas de dirección o haz clic para mover la pelota",
+ "HelpBounceToPosition": "Haz que la pelota rebote a un lugar",
+ "HelpOfTheWay": "del camino desde la parte izquierda de la barra",
+ "HelpGameOver": "Fin del juego. Pulsa el botón \"Jugar\" para iniciar otra partida",
+ "TutoTitle": "Actividad \"Fracción\"",
+ "TutoContent": "Bienvenido a la actividad \"Fracción\". En este juego, el alumno debe desplazar una pelota haciendo que bote sobre un punto de la parte inferior de la pantalla, que vendrá marcado con el valor estimado de una fracción dada",
+ "TutoBallTitle": "Pelota",
+ "TutoBallContent": "Haz clic en la pelota para iniciar la partida. Se mostrará una fracción/porcentaje encima de la pelota, que es la fracción en la que debes rebotarla",
+ "TutoBallControlsTitle": "Controles de la pelota",
+ "TutoBallControlsContent": "Usa las teclas de dirección izquierda y derecha para controlar la pelota. También podrás controlarla usando el ratón y haciendo clic a la izquierda o derecha de la misma. Por último, también podrás inclinar tu dispositivo",
+ "TutoSlopeTitle": "Pendiente",
+ "TutoSlopeContent": "La pendiente muestra las diferentes divisiones que tiene el intervalo entre 0 y 1 (o desde el 0 hasta el 100 %). Tendrás que hacer que la pelota bote en un punto de la pendiente donde esté la fracción definida a la izquierda de la pantalla",
+ "TutoLogTitle": "Registro",
+ "TutoLogContent": "En esta sección se muestra una tabla de respuestas del usuario",
+ "TutoPlayTitle": "Jugar/Pausar",
+ "TutoPlayContent": "Usa este botón para jugar o pausar tu partida",
+ "TutoSettingsTitle": "Ajustes",
+ "TutoSettingsContent": "Podrás añadir fracciones personalizadas en este menú. Las fracciones que definas aquí se añadirán a la lista de fracciones aleatorias que pueden usarse para crear una partida",
+ "TutoBallSelectTitle": "Estilo de la pelota",
+ "TutoBallSelectContent": "Se puede escoger la apariencia de la pelota de entre un grupo de temas predefinidos o usando una imagen de tu biblioteca",
+ "TutoBgSelectTitle": "Estilo de fondo",
+ "TutoBgSelectContent": "Podrás escoger el fondo de pantalla de entre un grupo predefinido de temas o de una imagen de tu biblioteca",
+ "TutoFractionsModeTitle": "Modo \"Fracción\"",
+ "TutoFractionsModeContent": "En este modo, se mostrará la fracción sobre la pelota",
+ "TutoSectorsModeTitle": "Modo \"Sectores\"",
+ "TutoSectorsModeContent": "En este modo, se mostrará la fracción sobre la pelota en forma de círculo con sectores",
+ "TutoPercentsModeTitle": "Modo \"Porcentaje\"",
+ "TutoPercentsModeContent": "En este modo, se mostrará la fracción sobre la pelota en forma de porcentaje",
+ "Score": "puntaje :"
+}
diff --git a/activities/FractionBounce.activity/locales/fr.json b/activities/FractionBounce.activity/locales/fr.json
new file mode 100644
index 000000000..977173fac
--- /dev/null
+++ b/activities/FractionBounce.activity/locales/fr.json
@@ -0,0 +1,46 @@
+{
+ "FractionBounceActivity": "Activité Fraction",
+ "Help": "Aide",
+ "Undo": "Annuler",
+ "Fullscreen": "Plein écran",
+ "Level": "Niveau",
+ "Settings": "Paramètrage",
+ "Ball": "Balle",
+ "Bg": "Fond d'écran",
+ "Fractions": "Fractions",
+ "Sectors": "Secteurs",
+ "Percents": "Pourcentages",
+ "TutoPrev": "Préc",
+ "TutoNext": "Suiv",
+ "TutoEnd": "Fin",
+ "Template": "Modèles",
+ "HelpClickToStart": "Play pour démarrer. Clic ou flèches pour déplacer balle",
+ "HelpBounceToPosition": "Rebondir à",
+ "HelpOfTheWay": "du bas de la pente",
+ "HelpGameOver": "Fini ! Play pour redémarrer",
+ "TutoTitle": "Activité Fraction",
+ "TutoContent": "Bienvenue dans l'activité Franction. Fraction est un jeu où il faut déplacer une balle rebondissante pour qu'elle rebondisse à l'endroit de la fraction",
+ "TutoBallTitle": "Balle",
+ "TutoBallContent": "Cliquez sur la balle pour démarrer. Une fraction ou un pourcentage sera affiché au dessus de la balle. C'est l'endroit où il faudra la faire atterrir",
+ "TutoBallControlsTitle": "Contrôle Balle",
+ "TutoBallControlsContent": "Utilisez les flèches du clavier pour contrôler la balle. Vous pouvez aussi la contrôler en cliquant à sa gauche ou à sa droite ou en penchant votre machine",
+ "TutoSlopeTitle": "Pente",
+ "TutoSlopeContent": "La pente affiche les différentes divisions dans l'intervalle 0 à 1 (ou 0 à 100%). Vous devez faire rebondir la balle sur la pente à l'endroit correspondant à la distance de la fraction depuis la gauche",
+ "TutoLogTitle": "Journal",
+ "TutoLogContent": "Cette section affiche une table avec les réponses qui ont été données",
+ "TutoPlayTitle": "Play/Pause",
+ "TutoPlayContent": "Utilisez ce bouton pour lancer ou mettre en pause le jeu",
+ "TutoSettingsTitle": "Paramètrage",
+ "TutoSettingsContent": "Ici vous pouvez ajouter des fractions. Ces fractions seront ajoutées à la liste des fractions qui peuvent être proposées à l'utilisateur",
+ "TutoBallSelectTitle": "Style Balle",
+ "TutoBallSelectContent": "Le style de la balle peut être choisi parmi une liste ou en utilisant une image du Journal",
+ "TutoBgSelectTitle": "Style Fond",
+ "TutoBgSelectContent": "Le fond d'écran peut être choisi parmi une liste ou en utilisant une image du Journal",
+ "TutoFractionsModeTitle": "Mode Fraction",
+ "TutoFractionsModeContent": "Dans ce mode, des fractions seront affichés sur la balle",
+ "TutoSectorsModeTitle": "Mode Secteur",
+ "TutoSectorsModeContent": "Dans ce mode, le secteur correspondant à la fraction à trouver est affiché au dessus de la balle",
+ "TutoPercentsModeTitle": "Mode Pourcentage",
+ "TutoPercentsModeContent": "Dans ce mode, le pourcentage correspondant à la fraction est affiché au dessus de la balle",
+ "Score": "score :"
+}
diff --git a/activities/FractionBounce.activity/po/en.po b/activities/FractionBounce.activity/po/en.po
deleted file mode 100644
index 9d2be4ab4..000000000
--- a/activities/FractionBounce.activity/po/en.po
+++ /dev/null
@@ -1,230 +0,0 @@
-#. extracted from ../locale.ini
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: Sun Apr 11 2021 11:20:31 GMT+0200 (heure d’été d’Europe centrale)\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: ini2po 0.0.1\n"
-
-#: FractionBounceActivity
-msgctxt "FractionBounceActivity"
-msgid "Fraction Activity"
-msgstr "Fraction Activity"
-
-#: Help
-msgctxt "Help"
-msgid "Help"
-msgstr "Help"
-
-#: Undo
-msgctxt "Undo"
-msgid "Undo"
-msgstr "Undo"
-
-#: Fullscreen
-msgctxt "Fullscreen"
-msgid "Fullscreen"
-msgstr "Fullscreen"
-
-#: Level
-msgctxt "Level"
-msgid "Level"
-msgstr "Level"
-
-#: Settings
-msgctxt "Settings"
-msgid "Settings"
-msgstr "Settings"
-
-#: Ball
-msgctxt "Ball"
-msgid "Ball"
-msgstr "Ball"
-
-#: Bg
-msgctxt "Bg"
-msgid "Background"
-msgstr "Background"
-
-#: Fractions
-msgctxt "Fractions"
-msgid "Fractions"
-msgstr "Fractions"
-
-#: Sectors
-msgctxt "Sectors"
-msgid "Sectors"
-msgstr "Sectors"
-
-#: Percents
-msgctxt "Percents"
-msgid "Percents"
-msgstr "Percents"
-
-#: PrevShort
-msgctxt "PrevShort"
-msgid "Prev"
-msgstr "Prev"
-
-#: NextShort
-msgctxt "NextShort"
-msgid "Next"
-msgstr "Next"
-
-#: EndShort
-msgctxt "EndShort"
-msgid "End"
-msgstr "End"
-
-#: Template
-msgctxt "Template"
-msgid "Templates"
-msgstr "Templates"
-
-#: HelpClickToStart
-msgctxt "HelpClickToStart"
-msgid "Click on play to start. Use arrow keys or click to move the ball"
-msgstr "Click on play to start. Use arrow keys or click to move the ball"
-
-#: HelpBounceToPosition
-msgctxt "HelpBounceToPosition"
-msgid "Bounce the ball to a position"
-msgstr "Bounce the ball to a position"
-
-#: HelpOfTheWay
-msgctxt "HelpOfTheWay"
-msgid "of the way from the left side of the bar"
-msgstr "of the way from the left side of the bar"
-
-#: HelpGameOver
-msgctxt "HelpGameOver"
-msgid "Game Over. Press the play button to start again"
-msgstr "Game Over. Press the play button to start again"
-
-#: TutoTitle
-msgctxt "TutoTitle"
-msgid "Fraction activity"
-msgstr "Fraction activity"
-
-#: TutoContent
-msgctxt "TutoContent"
-msgid "Welcome to the Fraction activity. This is a game that prompts the player to nudge a bouncing ball to land at a point on the bottom of the screen that is an estimate of a given fraction"
-msgstr "Welcome to the Fraction activity. This is a game that prompts the player to nudge a bouncing ball to land at a point on the bottom of the screen that is an estimate of a given fraction"
-
-#: TutoBallTitle
-msgctxt "TutoBallTitle"
-msgid "Ball"
-msgstr "Ball"
-
-#: TutoBallContent
-msgctxt "TutoBallContent"
-msgid "Click on the ball to start the game. A fraction/percentage will be shown on top of the ball signifying the fraction to land on"
-msgstr "Click on the ball to start the game. A fraction/percentage will be shown on top of the ball signifying the fraction to land on"
-
-#: TutoBallControlsTitle
-msgctxt "TutoBallControlsTitle"
-msgid "Ball Controls"
-msgstr "Ball Controls"
-
-#: TutoBallControlsContent
-msgctxt "TutoBallControlsContent"
-msgid "Use left and right arrow keys to control the ball. You can also control the ball using mouse by clicking to the left or right of the ball or by tilting your device"
-msgstr "Use left and right arrow keys to control the ball. You can also control the ball using mouse by clicking to the left or right of the ball or by tilting your device"
-
-#: TutoSlopeTitle
-msgctxt "TutoSlopeTitle"
-msgid "Slope"
-msgstr "Slope"
-
-#: TutoSlopeContent
-msgctxt "TutoSlopeContent"
-msgid "The slope shows the various divisions for the interval 0 to 1 (or 0 to 100%). You will have to bounce the ball somewhere on the slope at the specified fraction distance from the left"
-msgstr "The slope shows the various divisions for the interval 0 to 1 (or 0 to 100%). You will have to bounce the ball somewhere on the slope at the specified fraction distance from the left"
-
-#: TutoLogTitle
-msgctxt "TutoLogTitle"
-msgid "Log"
-msgstr "Log"
-
-#: TutoLogContent
-msgctxt "TutoLogContent"
-msgid "This section will show a table of answers made by the user"
-msgstr "This section will show a table of answers made by the user"
-
-#: TutoPlayTitle
-msgctxt "TutoPlayTitle"
-msgid "Play/Pause"
-msgstr "Play/Pause"
-
-#: TutoPlayContent
-msgctxt "TutoPlayContent"
-msgid "Use this button to play or pause your game"
-msgstr "Use this button to play or pause your game"
-
-#: TutoSettingsTitle
-msgctxt "TutoSettingsTitle"
-msgid "Settings"
-msgstr "Settings"
-
-#: TutoSettingsContent
-msgctxt "TutoSettingsContent"
-msgid "Custom fractions can be added here. These fractions will be added to the random list of fractions proposed to the user"
-msgstr "Custom fractions can be added here. These fractions will be added to the random list of fractions proposed to the user"
-
-#: TutoBallSelectTitle
-msgctxt "TutoBallSelectTitle"
-msgid "Ball Style"
-msgstr "Ball Style"
-
-#: TutoBallSelectContent
-msgctxt "TutoBallSelectContent"
-msgid "The ball can be chosen from one of the presets or an image from the journal"
-msgstr "The ball can be chosen from one of the presets or an image from the journal"
-
-#: TutoBgSelectTitle
-msgctxt "TutoBgSelectTitle"
-msgid "Background Style"
-msgstr "Background Style"
-
-#: TutoBgSelectContent
-msgctxt "TutoBgSelectContent"
-msgid "The background can be chosen from one of the presets or an image from the journal"
-msgstr "The background can be chosen from one of the presets or an image from the journal"
-
-#: TutoFractionsModeTitle
-msgctxt "TutoFractionsModeTitle"
-msgid "Fraction Mode"
-msgstr "Fraction Mode"
-
-#: TutoFractionsModeContent
-msgctxt "TutoFractionsModeContent"
-msgid "In this mode, fraction will be displayed over the ball"
-msgstr "In this mode, fraction will be displayed over the ball"
-
-#: TutoSectorsModeTitle
-msgctxt "TutoSectorsModeTitle"
-msgid "Sectors Mode"
-msgstr "Sectors Mode"
-
-#: TutoSectorsModeContent
-msgctxt "TutoSectorsModeContent"
-msgid "In this mode, sectors of a circle denoting the fraction will be displayed over the ball"
-msgstr "In this mode, sectors of a circle denoting the fraction will be displayed over the ball"
-
-#: TutoPercentsModeTitle
-msgctxt "TutoPercentsModeTitle"
-msgid "Percents Mode"
-msgstr "Percents Mode"
-
-#: TutoPercentsModeContent
-msgctxt "TutoPercentsModeContent"
-msgid "In this mode, percentage denoting the fraction will be displayed over the ball"
-msgstr "In this mode, percentage denoting the fraction will be displayed over the ball"
-
diff --git a/activities/FractionBounce.activity/po/es.po b/activities/FractionBounce.activity/po/es.po
deleted file mode 100644
index 3bc84aa85..000000000
--- a/activities/FractionBounce.activity/po/es.po
+++ /dev/null
@@ -1,230 +0,0 @@
-#. extracted from ../locale.ini
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: Sun Apr 11 2021 11:20:31 GMT+0200 (heure d’été d’Europe centrale)\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: ini2po 0.0.1\n"
-
-#: FractionBounceActivity
-msgctxt "FractionBounceActivity"
-msgid "Fraction Activity"
-msgstr "Actividad \"Fracción\""
-
-#: Help
-msgctxt "Help"
-msgid "Help"
-msgstr "Ayuda"
-
-#: Undo
-msgctxt "Undo"
-msgid "Undo"
-msgstr "Deshacer"
-
-#: Fullscreen
-msgctxt "Fullscreen"
-msgid "Fullscreen"
-msgstr "Pantalla completa"
-
-#: Level
-msgctxt "Level"
-msgid "Level"
-msgstr "Level"
-
-#: Settings
-msgctxt "Settings"
-msgid "Settings"
-msgstr "Ajustes"
-
-#: Ball
-msgctxt "Ball"
-msgid "Ball"
-msgstr "Pelota"
-
-#: Bg
-msgctxt "Bg"
-msgid "Background"
-msgstr "Fondo"
-
-#: Fractions
-msgctxt "Fractions"
-msgid "Fractions"
-msgstr "Fracciones"
-
-#: Sectors
-msgctxt "Sectors"
-msgid "Sectors"
-msgstr "Sectores"
-
-#: Percents
-msgctxt "Percents"
-msgid "Percents"
-msgstr "Porcentajes"
-
-#: PrevShort
-msgctxt "PrevShort"
-msgid "Prev"
-msgstr "Ant"
-
-#: NextShort
-msgctxt "NextShort"
-msgid "Next"
-msgstr "Sig"
-
-#: EndShort
-msgctxt "EndShort"
-msgid "End"
-msgstr "Fin"
-
-#: Template
-msgctxt "Template"
-msgid "Templates"
-msgstr "Plantillas"
-
-#: HelpClickToStart
-msgctxt "HelpClickToStart"
-msgid "Click on play to start. Use arrow keys or click to move the ball"
-msgstr "Haz clic en \"Jugar\" para iniciar el juego. Usa las teclas de dirección o haz clic para mover la pelota"
-
-#: HelpBounceToPosition
-msgctxt "HelpBounceToPosition"
-msgid "Bounce the ball to a position"
-msgstr "Haz que la pelota rebote a un lugar"
-
-#: HelpOfTheWay
-msgctxt "HelpOfTheWay"
-msgid "of the way from the left side of the bar"
-msgstr "del camino desde la parte izquierda de la barra"
-
-#: HelpGameOver
-msgctxt "HelpGameOver"
-msgid "Game Over. Press the play button to start again"
-msgstr "Fin del juego. Pulsa el botón \"Jugar\" para iniciar otra partida"
-
-#: TutoTitle
-msgctxt "TutoTitle"
-msgid "Fraction activity"
-msgstr "Actividad \"Fracción\""
-
-#: TutoContent
-msgctxt "TutoContent"
-msgid "Welcome to the Fraction activity. This is a game that prompts the player to nudge a bouncing ball to land at a point on the bottom of the screen that is an estimate of a given fraction"
-msgstr "Bienvenido a la actividad \"Fracción\". En este juego, el alumno debe desplazar una pelota haciendo que bote sobre un punto de la parte inferior de la pantalla, que vendrá marcado con el valor estimado de una fracción dada"
-
-#: TutoBallTitle
-msgctxt "TutoBallTitle"
-msgid "Ball"
-msgstr "Pelota"
-
-#: TutoBallContent
-msgctxt "TutoBallContent"
-msgid "Click on the ball to start the game. A fraction/percentage will be shown on top of the ball signifying the fraction to land on"
-msgstr "Haz clic en la pelota para iniciar la partida. Se mostrará una fracción/porcentaje encima de la pelota, que es la fracción en la que debes rebotarla"
-
-#: TutoBallControlsTitle
-msgctxt "TutoBallControlsTitle"
-msgid "Ball Controls"
-msgstr "Controles de la pelota"
-
-#: TutoBallControlsContent
-msgctxt "TutoBallControlsContent"
-msgid "Use left and right arrow keys to control the ball. You can also control the ball using mouse by clicking to the left or right of the ball or by tilting your device"
-msgstr "Usa las teclas de dirección izquierda y derecha para controlar la pelota. También podrás controlarla usando el ratón y haciendo clic a la izquierda o derecha de la misma. Por último, también podrás inclinar tu dispositivo"
-
-#: TutoSlopeTitle
-msgctxt "TutoSlopeTitle"
-msgid "Slope"
-msgstr "Pendiente"
-
-#: TutoSlopeContent
-msgctxt "TutoSlopeContent"
-msgid "The slope shows the various divisions for the interval 0 to 1 (or 0 to 100%). You will have to bounce the ball somewhere on the slope at the specified fraction distance from the left"
-msgstr "La pendiente muestra las diferentes divisiones que tiene el intervalo entre 0 y 1 (o desde el 0 hasta el 100 %). Tendrás que hacer que la pelota bote en un punto de la pendiente donde esté la fracción definida a la izquierda de la pantalla"
-
-#: TutoLogTitle
-msgctxt "TutoLogTitle"
-msgid "Log"
-msgstr "Registro"
-
-#: TutoLogContent
-msgctxt "TutoLogContent"
-msgid "This section will show a table of answers made by the user"
-msgstr "En esta sección se muestra una tabla de respuestas del usuario"
-
-#: TutoPlayTitle
-msgctxt "TutoPlayTitle"
-msgid "Play/Pause"
-msgstr "Jugar/Pausar"
-
-#: TutoPlayContent
-msgctxt "TutoPlayContent"
-msgid "Use this button to play or pause your game"
-msgstr "Usa este botón para jugar o pausar tu partida"
-
-#: TutoSettingsTitle
-msgctxt "TutoSettingsTitle"
-msgid "Settings"
-msgstr "Ajustes"
-
-#: TutoSettingsContent
-msgctxt "TutoSettingsContent"
-msgid "Custom fractions can be added here. These fractions will be added to the random list of fractions proposed to the user"
-msgstr "Podrás añadir fracciones personalizadas en este menú. Las fracciones que definas aquí se añadirán a la lista de fracciones aleatorias que pueden usarse para crear una partida"
-
-#: TutoBallSelectTitle
-msgctxt "TutoBallSelectTitle"
-msgid "Ball Style"
-msgstr "Estilo de la pelota"
-
-#: TutoBallSelectContent
-msgctxt "TutoBallSelectContent"
-msgid "The ball can be chosen from one of the presets or an image from the journal"
-msgstr "Se puede escoger la apariencia de la pelota de entre un grupo de temas predefinidos o usando una imagen de tu biblioteca"
-
-#: TutoBgSelectTitle
-msgctxt "TutoBgSelectTitle"
-msgid "Background Style"
-msgstr "Estilo de fondo"
-
-#: TutoBgSelectContent
-msgctxt "TutoBgSelectContent"
-msgid "The background can be chosen from one of the presets or an image from the journal"
-msgstr "Podrás escoger el fondo de pantalla de entre un grupo predefinido de temas o de una imagen de tu biblioteca"
-
-#: TutoFractionsModeTitle
-msgctxt "TutoFractionsModeTitle"
-msgid "Fraction Mode"
-msgstr "Modo \"Fracción\""
-
-#: TutoFractionsModeContent
-msgctxt "TutoFractionsModeContent"
-msgid "In this mode, fraction will be displayed over the ball"
-msgstr "En este modo, se mostrará la fracción sobre la pelota"
-
-#: TutoSectorsModeTitle
-msgctxt "TutoSectorsModeTitle"
-msgid "Sectors Mode"
-msgstr "Modo \"Sectores\""
-
-#: TutoSectorsModeContent
-msgctxt "TutoSectorsModeContent"
-msgid "In this mode, sectors of a circle denoting the fraction will be displayed over the ball"
-msgstr "En este modo, se mostrará la fracción sobre la pelota en forma de círculo con sectores"
-
-#: TutoPercentsModeTitle
-msgctxt "TutoPercentsModeTitle"
-msgid "Percents Mode"
-msgstr "Modo \"Porcentaje\""
-
-#: TutoPercentsModeContent
-msgctxt "TutoPercentsModeContent"
-msgid "In this mode, percentage denoting the fraction will be displayed over the ball"
-msgstr "En este modo, se mostrará la fracción sobre la pelota en forma de porcentaje"
-
diff --git a/activities/FractionBounce.activity/po/fr.po b/activities/FractionBounce.activity/po/fr.po
deleted file mode 100644
index a58ad9ddb..000000000
--- a/activities/FractionBounce.activity/po/fr.po
+++ /dev/null
@@ -1,230 +0,0 @@
-#. extracted from ../locale.ini
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: Sun Apr 11 2021 11:20:31 GMT+0200 (heure d’été d’Europe centrale)\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: ini2po 0.0.1\n"
-
-#: FractionBounceActivity
-msgctxt "FractionBounceActivity"
-msgid "Fraction Activity"
-msgstr "Activité Fraction"
-
-#: Help
-msgctxt "Help"
-msgid "Help"
-msgstr "Aide"
-
-#: Undo
-msgctxt "Undo"
-msgid "Undo"
-msgstr "Annuler"
-
-#: Fullscreen
-msgctxt "Fullscreen"
-msgid "Fullscreen"
-msgstr "Plein écran"
-
-#: Level
-msgctxt "Level"
-msgid "Level"
-msgstr "Niveau"
-
-#: Settings
-msgctxt "Settings"
-msgid "Settings"
-msgstr "Paramètrage"
-
-#: Ball
-msgctxt "Ball"
-msgid "Ball"
-msgstr "Balle"
-
-#: Bg
-msgctxt "Bg"
-msgid "Background"
-msgstr "Fond d'écran"
-
-#: Fractions
-msgctxt "Fractions"
-msgid "Fractions"
-msgstr "Fractions"
-
-#: Sectors
-msgctxt "Sectors"
-msgid "Sectors"
-msgstr "Secteurs"
-
-#: Percents
-msgctxt "Percents"
-msgid "Percents"
-msgstr "Pourcentages"
-
-#: PrevShort
-msgctxt "PrevShort"
-msgid "Prev"
-msgstr "Préc"
-
-#: NextShort
-msgctxt "NextShort"
-msgid "Next"
-msgstr "Suiv"
-
-#: EndShort
-msgctxt "EndShort"
-msgid "End"
-msgstr "Fin"
-
-#: Template
-msgctxt "Template"
-msgid "Templates"
-msgstr "Modèles"
-
-#: HelpClickToStart
-msgctxt "HelpClickToStart"
-msgid "Click on play to start. Use arrow keys or click to move the ball"
-msgstr "Play pour démarrer. Clic ou flèches pour déplacer balle"
-
-#: HelpBounceToPosition
-msgctxt "HelpBounceToPosition"
-msgid "Bounce the ball to a position"
-msgstr "Rebondir à"
-
-#: HelpOfTheWay
-msgctxt "HelpOfTheWay"
-msgid "of the way from the left side of the bar"
-msgstr "du bas de la pente"
-
-#: HelpGameOver
-msgctxt "HelpGameOver"
-msgid "Game Over. Press the play button to start again"
-msgstr "Fini ! Play pour redémarrer"
-
-#: TutoTitle
-msgctxt "TutoTitle"
-msgid "Fraction activity"
-msgstr "Activité Fraction"
-
-#: TutoContent
-msgctxt "TutoContent"
-msgid "Welcome to the Fraction activity. This is a game that prompts the player to nudge a bouncing ball to land at a point on the bottom of the screen that is an estimate of a given fraction"
-msgstr "Bienvenue dans l'activité Franction. Fraction est un jeu où il faut déplacer une balle rebondissante pour qu'elle rebondisse à l'endroit de la fraction"
-
-#: TutoBallTitle
-msgctxt "TutoBallTitle"
-msgid "Ball"
-msgstr "Balle"
-
-#: TutoBallContent
-msgctxt "TutoBallContent"
-msgid "Click on the ball to start the game. A fraction/percentage will be shown on top of the ball signifying the fraction to land on"
-msgstr "Cliquez sur la balle pour démarrer. Une fraction ou un pourcentage sera affiché au dessus de la balle. C'est l'endroit où il faudra la faire atterrir"
-
-#: TutoBallControlsTitle
-msgctxt "TutoBallControlsTitle"
-msgid "Ball Controls"
-msgstr "Contrôle Balle"
-
-#: TutoBallControlsContent
-msgctxt "TutoBallControlsContent"
-msgid "Use left and right arrow keys to control the ball. You can also control the ball using mouse by clicking to the left or right of the ball or by tilting your device"
-msgstr "Utilisez les flèches du clavier pour contrôler la balle. Vous pouvez aussi la contrôler en cliquant à sa gauche ou à sa droite ou en penchant votre machine"
-
-#: TutoSlopeTitle
-msgctxt "TutoSlopeTitle"
-msgid "Slope"
-msgstr "Pente"
-
-#: TutoSlopeContent
-msgctxt "TutoSlopeContent"
-msgid "The slope shows the various divisions for the interval 0 to 1 (or 0 to 100%). You will have to bounce the ball somewhere on the slope at the specified fraction distance from the left"
-msgstr "La pente affiche les différentes divisions dans l'intervalle 0 à 1 (ou 0 à 100%). Vous devez faire rebondir la balle sur la pente à l'endroit correspondant à la distance de la fraction depuis la gauche"
-
-#: TutoLogTitle
-msgctxt "TutoLogTitle"
-msgid "Log"
-msgstr "Journal"
-
-#: TutoLogContent
-msgctxt "TutoLogContent"
-msgid "This section will show a table of answers made by the user"
-msgstr "Cette section affiche une table avec les réponses qui ont été données"
-
-#: TutoPlayTitle
-msgctxt "TutoPlayTitle"
-msgid "Play/Pause"
-msgstr "Play/Pause"
-
-#: TutoPlayContent
-msgctxt "TutoPlayContent"
-msgid "Use this button to play or pause your game"
-msgstr "Utilisez ce bouton pour lancer ou mettre en pause le jeu"
-
-#: TutoSettingsTitle
-msgctxt "TutoSettingsTitle"
-msgid "Settings"
-msgstr "Paramètrage"
-
-#: TutoSettingsContent
-msgctxt "TutoSettingsContent"
-msgid "Custom fractions can be added here. These fractions will be added to the random list of fractions proposed to the user"
-msgstr "Ici vous pouvez ajouter des fractions. Ces fractions seront ajoutées à la liste des fractions qui peuvent être proposées à l'utilisateur"
-
-#: TutoBallSelectTitle
-msgctxt "TutoBallSelectTitle"
-msgid "Ball Style"
-msgstr "Style Balle"
-
-#: TutoBallSelectContent
-msgctxt "TutoBallSelectContent"
-msgid "The ball can be chosen from one of the presets or an image from the journal"
-msgstr "Le style de la balle peut être choisi parmi une liste ou en utilisant une image du Journal"
-
-#: TutoBgSelectTitle
-msgctxt "TutoBgSelectTitle"
-msgid "Background Style"
-msgstr "Style Fond"
-
-#: TutoBgSelectContent
-msgctxt "TutoBgSelectContent"
-msgid "The background can be chosen from one of the presets or an image from the journal"
-msgstr "Le fond d'écran peut être choisi parmi une liste ou en utilisant une image du Journal"
-
-#: TutoFractionsModeTitle
-msgctxt "TutoFractionsModeTitle"
-msgid "Fraction Mode"
-msgstr "Mode Fraction"
-
-#: TutoFractionsModeContent
-msgctxt "TutoFractionsModeContent"
-msgid "In this mode, fraction will be displayed over the ball"
-msgstr "Dans ce mode, des fractions seront affichés sur la balle"
-
-#: TutoSectorsModeTitle
-msgctxt "TutoSectorsModeTitle"
-msgid "Sectors Mode"
-msgstr "Mode Secteur"
-
-#: TutoSectorsModeContent
-msgctxt "TutoSectorsModeContent"
-msgid "In this mode, sectors of a circle denoting the fraction will be displayed over the ball"
-msgstr "Dans ce mode, le secteur correspondant à la fraction à trouver est affiché au dessus de la balle"
-
-#: TutoPercentsModeTitle
-msgctxt "TutoPercentsModeTitle"
-msgid "Percents Mode"
-msgstr "Mode Pourcentage"
-
-#: TutoPercentsModeContent
-msgctxt "TutoPercentsModeContent"
-msgid "In this mode, percentage denoting the fraction will be displayed over the ball"
-msgstr "Dans ce mode, le pourcentage correspondant à la fraction est affiché au dessus de la balle"
-
diff --git a/activities/FractionBounce.activity/po/template.pot b/activities/FractionBounce.activity/po/template.pot
deleted file mode 100644
index 8d6c85ace..000000000
--- a/activities/FractionBounce.activity/po/template.pot
+++ /dev/null
@@ -1,230 +0,0 @@
-#. extracted from ../locale.ini
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: Sat May 08 2021 22:09:13 GMT+0200 (heure d’été d’Europe centrale)\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: ini2po 0.0.1\n"
-
-#: FractionBounceActivity
-msgctxt "FractionBounceActivity"
-msgid "Fraction Activity"
-msgstr "Fraction Activity"
-
-#: Help
-msgctxt "Help"
-msgid "Help"
-msgstr "Help"
-
-#: Undo
-msgctxt "Undo"
-msgid "Undo"
-msgstr "Undo"
-
-#: Fullscreen
-msgctxt "Fullscreen"
-msgid "Fullscreen"
-msgstr "Fullscreen"
-
-#: Level
-msgctxt "Level"
-msgid "Level"
-msgstr "Level"
-
-#: Settings
-msgctxt "Settings"
-msgid "Settings"
-msgstr "Settings"
-
-#: Ball
-msgctxt "Ball"
-msgid "Ball"
-msgstr "Ball"
-
-#: Bg
-msgctxt "Bg"
-msgid "Background"
-msgstr "Background"
-
-#: Fractions
-msgctxt "Fractions"
-msgid "Fractions"
-msgstr "Fractions"
-
-#: Sectors
-msgctxt "Sectors"
-msgid "Sectors"
-msgstr "Sectors"
-
-#: Percents
-msgctxt "Percents"
-msgid "Percents"
-msgstr "Percents"
-
-#: PrevShort
-msgctxt "PrevShort"
-msgid "Prev"
-msgstr "Prev"
-
-#: NextShort
-msgctxt "NextShort"
-msgid "Next"
-msgstr "Next"
-
-#: EndShort
-msgctxt "EndShort"
-msgid "End"
-msgstr "End"
-
-#: Template
-msgctxt "Template"
-msgid "Templates"
-msgstr "Templates"
-
-#: HelpClickToStart
-msgctxt "HelpClickToStart"
-msgid "Click on play to start. Use arrow keys or click to move the ball"
-msgstr "Click on play to start. Use arrow keys or click to move the ball"
-
-#: HelpBounceToPosition
-msgctxt "HelpBounceToPosition"
-msgid "Bounce the ball to a position"
-msgstr "Bounce the ball to a position"
-
-#: HelpOfTheWay
-msgctxt "HelpOfTheWay"
-msgid "of the way from the left side of the bar"
-msgstr "of the way from the left side of the bar"
-
-#: HelpGameOver
-msgctxt "HelpGameOver"
-msgid "Game Over. Press the play button to start again"
-msgstr "Game Over. Press the play button to start again"
-
-#: TutoTitle
-msgctxt "TutoTitle"
-msgid "Fraction activity"
-msgstr "Fraction activity"
-
-#: TutoContent
-msgctxt "TutoContent"
-msgid "Welcome to the Fraction activity. This is a game that prompts the player to nudge a bouncing ball to land at a point on the bottom of the screen that is an estimate of a given fraction"
-msgstr "Welcome to the Fraction activity. This is a game that prompts the player to nudge a bouncing ball to land at a point on the bottom of the screen that is an estimate of a given fraction"
-
-#: TutoBallTitle
-msgctxt "TutoBallTitle"
-msgid "Ball"
-msgstr "Ball"
-
-#: TutoBallContent
-msgctxt "TutoBallContent"
-msgid "Click on the ball to start the game. A fraction/percentage will be shown on top of the ball signifying the fraction to land on"
-msgstr "Click on the ball to start the game. A fraction/percentage will be shown on top of the ball signifying the fraction to land on"
-
-#: TutoBallControlsTitle
-msgctxt "TutoBallControlsTitle"
-msgid "Ball Controls"
-msgstr "Ball Controls"
-
-#: TutoBallControlsContent
-msgctxt "TutoBallControlsContent"
-msgid "Use left and right arrow keys to control the ball. You can also control the ball using mouse by clicking to the left or right of the ball or by tilting your device"
-msgstr "Use left and right arrow keys to control the ball. You can also control the ball using mouse by clicking to the left or right of the ball or by tilting your device"
-
-#: TutoSlopeTitle
-msgctxt "TutoSlopeTitle"
-msgid "Slope"
-msgstr "Slope"
-
-#: TutoSlopeContent
-msgctxt "TutoSlopeContent"
-msgid "The slope shows the various divisions for the interval 0 to 1 (or 0 to 100%). You will have to bounce the ball somewhere on the slope at the specified fraction distance from the left"
-msgstr "The slope shows the various divisions for the interval 0 to 1 (or 0 to 100%). You will have to bounce the ball somewhere on the slope at the specified fraction distance from the left"
-
-#: TutoLogTitle
-msgctxt "TutoLogTitle"
-msgid "Log"
-msgstr "Log"
-
-#: TutoLogContent
-msgctxt "TutoLogContent"
-msgid "This section will show a table of answers made by the user"
-msgstr "This section will show a table of answers made by the user"
-
-#: TutoPlayTitle
-msgctxt "TutoPlayTitle"
-msgid "Play/Pause"
-msgstr "Play/Pause"
-
-#: TutoPlayContent
-msgctxt "TutoPlayContent"
-msgid "Use this button to play or pause your game"
-msgstr "Use this button to play or pause your game"
-
-#: TutoSettingsTitle
-msgctxt "TutoSettingsTitle"
-msgid "Settings"
-msgstr "Settings"
-
-#: TutoSettingsContent
-msgctxt "TutoSettingsContent"
-msgid "Custom fractions can be added here. These fractions will be added to the random list of fractions proposed to the user"
-msgstr "Custom fractions can be added here. These fractions will be added to the random list of fractions proposed to the user"
-
-#: TutoBallSelectTitle
-msgctxt "TutoBallSelectTitle"
-msgid "Ball Style"
-msgstr "Ball Style"
-
-#: TutoBallSelectContent
-msgctxt "TutoBallSelectContent"
-msgid "The ball can be chosen from one of the presets or an image from the journal"
-msgstr "The ball can be chosen from one of the presets or an image from the journal"
-
-#: TutoBgSelectTitle
-msgctxt "TutoBgSelectTitle"
-msgid "Background Style"
-msgstr "Background Style"
-
-#: TutoBgSelectContent
-msgctxt "TutoBgSelectContent"
-msgid "The background can be chosen from one of the presets or an image from the journal"
-msgstr "The background can be chosen from one of the presets or an image from the journal"
-
-#: TutoFractionsModeTitle
-msgctxt "TutoFractionsModeTitle"
-msgid "Fraction Mode"
-msgstr "Fraction Mode"
-
-#: TutoFractionsModeContent
-msgctxt "TutoFractionsModeContent"
-msgid "In this mode, fraction will be displayed over the ball"
-msgstr "In this mode, fraction will be displayed over the ball"
-
-#: TutoSectorsModeTitle
-msgctxt "TutoSectorsModeTitle"
-msgid "Sectors Mode"
-msgstr "Sectors Mode"
-
-#: TutoSectorsModeContent
-msgctxt "TutoSectorsModeContent"
-msgid "In this mode, sectors of a circle denoting the fraction will be displayed over the ball"
-msgstr "In this mode, sectors of a circle denoting the fraction will be displayed over the ball"
-
-#: TutoPercentsModeTitle
-msgctxt "TutoPercentsModeTitle"
-msgid "Percents Mode"
-msgstr "Percents Mode"
-
-#: TutoPercentsModeContent
-msgctxt "TutoPercentsModeContent"
-msgid "In this mode, percentage denoting the fraction will be displayed over the ball"
-msgstr "In this mode, percentage denoting the fraction will be displayed over the ball"
-