diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 451cb00c9c19b1e11fc357fa19162547f9e9a31a..522ac51c59ad499187aee5d451e5096bde325a77 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -37,6 +37,16 @@ docker-build-image-tag:
rules:
- if: '$CI_COMMIT_TAG'
+check:
+ stage: build
+ image: node:23-alpine
+ script:
+ - cd app
+ - npm install
+ - npm run check
+ rules:
+ - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+
deploy_staging:
stage: deploy-staging
needs: ["docker-build-image-latest"]
diff --git a/app/.prettierignore b/app/.prettierignore
new file mode 100644
index 0000000000000000000000000000000000000000..ea0e65aedf916ec5de7d17749ccbe4a1287ecf55
--- /dev/null
+++ b/app/.prettierignore
@@ -0,0 +1,3 @@
+# Ignore artifacts:
+lib
+dist
diff --git a/app/.prettierrc b/app/.prettierrc
new file mode 100644
index 0000000000000000000000000000000000000000..0967ef424bce6791893e9a57bb952f80fd536e93
--- /dev/null
+++ b/app/.prettierrc
@@ -0,0 +1 @@
+{}
diff --git a/app/eslint.config.js b/app/eslint.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..29b428e82dd21b12dca6c6d8b8ee28bd0d39ecc9
--- /dev/null
+++ b/app/eslint.config.js
@@ -0,0 +1,9 @@
+import globals from "globals";
+import pluginJs from "@eslint/js";
+
+/** @type {import('eslint').Linter.Config[]} */
+export default [
+ { languageOptions: { globals: globals.browser } },
+ pluginJs.configs.recommended,
+ { ignores: ["src/lib/*", "dist/*"] },
+];
diff --git a/app/index.html b/app/index.html
index 44149d5f5de268572c8ce19d569f0d37372911b4..6f5040372801e62bdc24df22fdc7f5a9335ff4c1 100644
--- a/app/index.html
+++ b/app/index.html
@@ -1,630 +1,838 @@
-
-
-
-
-
-
-
-
- /e/OS Installer
-
-
-
-
-
-
-
-
-
-
-
-
-
Installation
-
1/?
-
completed
-
-
-
-
-
-

-
/e/OS Installer
-
-
-
-
-
-

-
-
-
-

-
-
-
-

-
-
-
-

-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-

-
-
-
-
-
-
-
-
-
-

-

-
-
-
-
-
-
-
-
-
-

-
-
-
-

-
-
-
-
-
-
-
-
-
-

-
-
-
-

-
-
-
-
-
-
-
-
-
-

-
-
-
-

-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-

-
-
-
-
-

-
Microsoft Edge 125.0.0
-
-
-

-
Opera 111.0.0
-
-
-

-
Chrome 126.0.0
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ /e/OS Installer
+
+
+
+
+
+
+
+
+
+
+
+
+
Installation
+
+ 1/?
+
+
completed
+
+
+
+
+

+
/e/OS Installer
+
+
+
+
+
+

+
+
+
+

+
+
+
+

+
+
+
+

+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
+
+
+
+
+
+
+

+

+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
+
+
+
+
+
+
+

+
+
+
+

+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+

+
+
+
+
+

+
Microsoft Edge 125.0.0
+
+
+

+
Opera 111.0.0
+
+
+

+
Chrome 126.0.0
+
+
+
+
+
+
+
diff --git a/app/package-lock.json b/app/package-lock.json
index 208923aff899f15af0866e35dfe4328fb4070cc9..6ba53db8e44aca4ebc681368950ba262e0d01cef 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -13,6 +13,10 @@
"ky": "^1.7.4"
},
"devDependencies": {
+ "@eslint/js": "^9.17.0",
+ "eslint": "^9.17.0",
+ "globals": "^15.14.0",
+ "prettier": "3.4.2",
"vite": "^6.0.5"
}
},
@@ -33,6 +37,212 @@
"node": ">=18"
}
},
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
+ "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz",
+ "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.5",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz",
+ "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz",
+ "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz",
+ "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz",
+ "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz",
+ "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.6",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
+ "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+ "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz",
+ "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.29.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz",
@@ -42,82 +252,650 @@
],
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz",
+ "integrity": "sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@zip.js/zip.js": {
+ "version": "2.7.54",
+ "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.7.54.tgz",
+ "integrity": "sha512-qMrJVg2hoEsZJjMJez9yI2+nZlBUxgYzGV3mqcb2B/6T1ihXp0fWBDYlVHlHquuorgNUQP5a8qSmX6HF5rFJNg==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "bun": ">=0.7.0",
+ "deno": ">=1.0.0",
+ "node": ">=16.5.0"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.14.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
+ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
+ "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/esbuild": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
+ "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.24.2",
+ "@esbuild/android-arm": "0.24.2",
+ "@esbuild/android-arm64": "0.24.2",
+ "@esbuild/android-x64": "0.24.2",
+ "@esbuild/darwin-arm64": "0.24.2",
+ "@esbuild/darwin-x64": "0.24.2",
+ "@esbuild/freebsd-arm64": "0.24.2",
+ "@esbuild/freebsd-x64": "0.24.2",
+ "@esbuild/linux-arm": "0.24.2",
+ "@esbuild/linux-arm64": "0.24.2",
+ "@esbuild/linux-ia32": "0.24.2",
+ "@esbuild/linux-loong64": "0.24.2",
+ "@esbuild/linux-mips64el": "0.24.2",
+ "@esbuild/linux-ppc64": "0.24.2",
+ "@esbuild/linux-riscv64": "0.24.2",
+ "@esbuild/linux-s390x": "0.24.2",
+ "@esbuild/linux-x64": "0.24.2",
+ "@esbuild/netbsd-arm64": "0.24.2",
+ "@esbuild/netbsd-x64": "0.24.2",
+ "@esbuild/openbsd-arm64": "0.24.2",
+ "@esbuild/openbsd-x64": "0.24.2",
+ "@esbuild/sunos-x64": "0.24.2",
+ "@esbuild/win32-arm64": "0.24.2",
+ "@esbuild/win32-ia32": "0.24.2",
+ "@esbuild/win32-x64": "0.24.2"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.17.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz",
+ "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.19.0",
+ "@eslint/core": "^0.9.0",
+ "@eslint/eslintrc": "^3.2.0",
+ "@eslint/js": "9.17.0",
+ "@eslint/plugin-kit": "^0.2.3",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.1",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.2.0",
+ "eslint-visitor-keys": "^4.2.0",
+ "espree": "^10.3.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
+ "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
+ "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
+ "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.14.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz",
+ "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "15.14.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
+ "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz",
- "integrity": "sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==",
- "cpu": [
- "x64"
- ],
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "engines": {
+ "node": ">=0.8.19"
+ }
},
- "node_modules/@types/estree": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
- "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
- "license": "MIT"
- },
- "node_modules/@zip.js/zip.js": {
- "version": "2.7.54",
- "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.7.54.tgz",
- "integrity": "sha512-qMrJVg2hoEsZJjMJez9yI2+nZlBUxgYzGV3mqcb2B/6T1ihXp0fWBDYlVHlHquuorgNUQP5a8qSmX6HF5rFJNg==",
- "license": "BSD-3-Clause",
+ "license": "MIT",
"engines": {
- "bun": ">=0.7.0",
- "deno": ">=1.0.0",
- "node": ">=16.5.0"
+ "node": ">=0.10.0"
}
},
- "node_modules/esbuild": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
- "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
- "hasInstallScript": true,
"license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
+ "dependencies": {
+ "is-extglob": "^2.1.1"
},
"engines": {
- "node": ">=18"
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
},
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.24.2",
- "@esbuild/android-arm": "0.24.2",
- "@esbuild/android-arm64": "0.24.2",
- "@esbuild/android-x64": "0.24.2",
- "@esbuild/darwin-arm64": "0.24.2",
- "@esbuild/darwin-x64": "0.24.2",
- "@esbuild/freebsd-arm64": "0.24.2",
- "@esbuild/freebsd-x64": "0.24.2",
- "@esbuild/linux-arm": "0.24.2",
- "@esbuild/linux-arm64": "0.24.2",
- "@esbuild/linux-ia32": "0.24.2",
- "@esbuild/linux-loong64": "0.24.2",
- "@esbuild/linux-mips64el": "0.24.2",
- "@esbuild/linux-ppc64": "0.24.2",
- "@esbuild/linux-riscv64": "0.24.2",
- "@esbuild/linux-s390x": "0.24.2",
- "@esbuild/linux-x64": "0.24.2",
- "@esbuild/netbsd-arm64": "0.24.2",
- "@esbuild/netbsd-x64": "0.24.2",
- "@esbuild/openbsd-arm64": "0.24.2",
- "@esbuild/openbsd-x64": "0.24.2",
- "@esbuild/sunos-x64": "0.24.2",
- "@esbuild/win32-arm64": "0.24.2",
- "@esbuild/win32-ia32": "0.24.2",
- "@esbuild/win32-x64": "0.24.2"
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
}
},
"node_modules/ky": {
@@ -132,6 +910,63 @@
"url": "https://github.com/sindresorhus/ky?sponsor=1"
}
},
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/nanoid": {
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
@@ -151,6 +986,96 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -187,6 +1112,52 @@
"node": "^10 || ^12 || >=14"
}
},
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
+ "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/rollup": {
"version": "4.29.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz",
@@ -226,6 +1197,29 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -236,6 +1230,55 @@
"node": ">=0.10.0"
}
},
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
"node_modules/vite": {
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.0.6.tgz",
@@ -307,6 +1350,45 @@
"optional": true
}
}
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
}
}
}
diff --git a/app/package.json b/app/package.json
index 63881d6e8584b9608bd9530c6037602291bbe701..ff2269abb7957d2a6aaa1c7d5059953ae65d32f7 100644
--- a/app/package.json
+++ b/app/package.json
@@ -6,9 +6,15 @@
"scripts": {
"dev": "vite",
"build": "vite build",
- "preview": "vite preview"
+ "preview": "vite preview",
+ "check": "npx eslint . && npx prettier . --check",
+ "format": "npx prettier . --write"
},
"devDependencies": {
+ "@eslint/js": "^9.17.0",
+ "eslint": "^9.17.0",
+ "globals": "^15.14.0",
+ "prettier": "3.4.2",
"vite": "^6.0.5"
},
"dependencies": {
diff --git a/app/public/assets/languages/de.json b/app/public/assets/languages/de.json
index 6fd519e2638164997e8a2dfc3a2ae931b05e13fb..2c61a8442949cc0b367eefadf7d9b729ca2582ee 100644
--- a/app/public/assets/languages/de.json
+++ b/app/public/assets/languages/de.json
@@ -1,111 +1,111 @@
{
- "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Beispiel 1: Bevor du /e/OS Android 12 installierst, solltest du auf die neueste Standardversion von Android 12 aktualisieren.",
- "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Beispiel 2: Oder wenn du /e/OS Android 11 installierst, stelle sicher, dass du vorher auf die neueste Standardversion von Android 11 aktualisierst.",
- "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Beispiel 3: Ähnlich, wenn du /e/OS Android 11 installierst, sollte es die neueste Standardversion von Android 10 sein.",
- "activate-developer-options": "Entwickleroptionen aktivieren",
- "activate-developer-options-instructions-1": "1. Öffne das Einstellungsmenü und gib ‘Build’ in die Suchleiste ein.",
- "activate-developer-options-instructions-2": "2. Auf dem nächsten Bildschirm finde ‘Build-Nummer’ und tippe 7 Mal darauf.",
- "activate-usb-debugging": "USB-Debugging aktivieren",
- "activate-usb-debugging-instructions-1": "1. Gehe zurück zum Einstellungsmenü und gib ‘USB-Debugging’ in die Suchleiste ein.",
- "activate-usb-debugging-instructions-2": "2. Zu diesem Zeitpunkt solltest du im Bildschirm ‘Entwickleroptionen’ sein. Tippe nun auf ‘USB-Debugging’, um es zu aktivieren (bei einigen Geräten wird es ‘Android-Debugging’ genannt).",
- "bootloader-to-recovery-manually": "Bootloader zu Recovery",
- "bootloader-to-recovery-manually-instructions": "Jetzt werden wir dein Gerät im Recovery-Modus neu starten. Bitte folge den untenstehenden Schritten:",
- "bootloader-to-recovery-manually-instructions-1": "1. Wähle im Bootloader Recovery Modus
aus, indem du Lautstärke lauter und Lautstärke leiser verwendest, um zu navigieren",
- "bootloader-to-recovery-manually-instructions-2": "2. Drücke Ausschalten, um zu bestätigen",
- "bootloader-to-recovery-manually-instructions-3": "3. Warte bis dein Telefon im Recovery-Modus neu startet",
- "check-update-android-version": "Überprüfe und aktualisiere deine Android-Version",
- "check-update-android-version-caution": "Vorsicht: Bevor du mit der Installation fortfährst, vergewissere dich, ob die neueste Android-Firmware für dein Gerät verfügbar ist.",
- "connect": "Verbinden",
- "connect-bootloader": "Bootloader-Verbindung",
- "connect-bootloader-instructions-1": "Dein Telefon wird jetzt im Bootloader
-Modus neu starten.",
- "connect-bootloader-instructions-2": "Wenn dein Telefon eingeschaltet ist, verbinde es im Bootloader
-Modus, indem du auf die untenstehende Schaltfläche tippst.",
- "connect-your-phone": "Verbinde dein Telefon",
- "connect-your-phone-instructions": "Verbinde dein Telefon mit einem USB-Kabel mit deinem Computer. Wir erkennen dein Telefon automatisch, um /e/OS zu installieren.",
- "connect-your-phone-instructions-notes": "Hinweis: ‘USB-Debugging’ ist erforderlich, damit die automatische Geräteerkennung funktioniert. Wenn du es noch nicht aktiviert hast, helfen wir dir in den nächsten Schritten.",
- "device-detection": "Geräteerkennung",
- "device-detection-detected": "Ein Gerät wurde erkannt.",
- "device-detection-instructions-1": "Wir verbinden jetzt dein Telefon mit dem Browser. Wenn dieses Pop-up erscheint, wähle dein Telefon aus der Liste aus.",
- "device-detection-instructions-2": "Es wird ein Pop-up-Fenster auf deinem Telefon erscheinen. Du musst Immer von diesem Computer zulassen
auswählen, bevor du auf OK drückst.",
- "device-detection-instructions-3": "Tippe auf die untenstehende Schaltfläche, um die Verbindung zu starten.",
- "device-model-not-supported": "Gerätemodell nicht unterstützt",
- "device-model-not-supported-instructions": "Du kannst /e/OS nicht mit diesem Programm installieren",
- "device-model-not-supported-title": "Dein Telefon {{product-name}} ist nicht kompatibel",
- "dissatisfied": "Unzufrieden",
- "donate": "Spenden",
- "enable-usb-file-transfer": "USB-Dateiübertragung aktivieren",
- "enable-usb-file-transfer-instructions-1": "Immer noch in den ‘Entwickleroptionen’, scrolle nach unten, um ‘Standard-USB-Konfiguration’ zu finden und tippe darauf.",
- "enable-usb-file-transfer-instructions-2": "Wähle jetzt die Option ‘Dateiübertragung’ (bei einigen Geräten wird es ‘MTP-Modus (Media Transfer Protocol)’ genannt).",
- "format-device": "Gerät formatieren",
- "format-device-instructions-1": "1. Wähle Werkseinstellung zurücksetzen
",
- "format-device-instructions-2": "2. Wähle die Option Daten formatieren / Werkseinstellung zurücksetzen
",
- "format-device-instructions-3": "3. Der nächste Bildschirm zeigt eine Warnung an, dass diese Aktion nicht rückgängig gemacht werden kann",
- "format-device-instructions-4": "4. Wähle Daten formatieren
, um fortzufahren",
- "format-device-instructions-5": "5. Bitte warten, der Formatierungsprozess wird abgeschlossen",
- "format-device-instructions-6": "6. Der Bildschirm kehrt jetzt zum Werkseinstellungsbildschirm zurück",
- "go-to-apply-update": "Fast geschafft!",
- "go-to-apply-update-instructions-1": "1. Wähle Aktualisierung anwenden
",
- "go-to-apply-update-instructions-2": "2. und dann Aktualisierung von adb anwenden
",
- "go-to-apply-update-instructions-3": "3. Das Gerät befindet sich jetzt im Sideload-Modus und du bist bereit für den nächsten Schritt.",
- "help": "Hilfe",
- "help-us-improve-the-tool": "Hilf uns, das Programm zu verbessern",
- "help-us-improve-the-tool-instructions-1": "Bitte bewerte deine Erfahrung mit dem /e/OS Installer.",
- "help-us-improve-the-tool-instructions-2": "Hast du irgendwelche Idee dazu, wie wir dieses Programm verbessern können?",
- "i-already-have-an-account": "Ich habe bereits ein Konto",
- "i-m-ready": "Ich bin bereit!",
- "installation-complete": "Die Installation ist abgeschlossen!",
- "installation-complete-instructions-1": "Glückwunsch! Während dein Telefon hochfährt, solltest du das untenstehende Logo sehen. Das kann eine Weile dauern, bitte habe etwas Geduld.",
- "installation-complete-instructions-2": "Tipp: Folge den Anweisungen auf deinem Telefon, um dein Gerät einzurichten. Du kannst jetzt deine Dateien zurück auf dein Telefon übertragen.",
- "let-s-get-started": "Los geht's",
- "let-s-get-started-instruction-1": "Der komplette Installationsprozess dauert etwa 1 Stunde. Bring etwas Geduld mit!",
- "let-s-get-started-instruction-2": "Du brauchst mindestens 6 GB freien Speicherplatz auf deinem Computer, um /e/OS herunterzuladen und zu installieren. Stelle sicher, dass du genügend freien Speicherplatz hast.",
- "let-s-get-started-instruction-3": "Bevor du /e/OS installierst, stelle sicher, dass dein Telefon mindestens 50% Akku hat.",
- "let-s-get-started-instruction-4": "Alle Daten werden während der Installation von deinem Smartphone gelöscht, daher empfehlen wir, deine Daten vorher zu sichern.",
- "let-s-get-started-instruction-5": "Ein funktionierendes USB-Datenkabel ist erforderlich. Stromkabel übertragen keine Daten und funktionieren nicht! Wir empfehlen USB 3.x oder neuer.",
- "let-s-get-started-instruction-title-1": "1. Nimm dir etwas freie Zeit",
- "let-s-get-started-instruction-title-2": "2. Mach Platz auf deiner Festplatte",
- "let-s-get-started-instruction-title-3": "3. Lade dein Telefon auf",
- "let-s-get-started-instruction-title-4": "4. Sichere deine Daten",
- "let-s-get-started-instruction-title-5": "5. Hol dir ein USB-Datenkabel",
- "locking": "Sperren",
- "locking-instructions-1": "Dein Telefon fragt nach einer Sperre. Wähle lock bootloader
",
- "locking-instructions-2": "Wenn sich das Gerät nicht automatisch neu startet, starte es neu",
- "murena-workspace-account": "Murena Workspace-Konto",
- "murena-workspace-account-instructions": "Sichere deine Daten und synchronisiere dieses Gerät mit deinem persönlichen Murena Workspace-Konto. 1 GB sind kostenlos, es gibt auch ein Bezahl-Abo für mehr Speicherplatz.",
- "navigator-detection": "Browser-Erkennung",
- "navigator-not-supported": "Dein Browser wird nicht unterstützt",
- "navigator-not-supported-instructions": "Du kannst die folgenden Browser verwenden",
- "neutral": "Neutral",
- "next": "Weiter",
- "ready-to-install-e-os": "Du bist jetzt bereit, /e/OS zu installieren.",
- "recovery-to-bootloader": "Recovery zu Bootloader",
- "recovery-to-bootloader-instructions": "Im Hauptmenü",
- "recovery-to-bootloader-instructions-1": "1. Wähle Erweitert
",
- "recovery-to-bootloader-instructions-2": "2. Wähle Reboot to bootloader
",
- "satisfied": "Zufrieden",
- "send-to-e-team": "An das Murena Team senden",
- "sideload": "Installation läuft",
- "sideload-instructions-1": "Der Bildschirm zeigt den Fortschritt an … ",
- "sideload-instructions-2": "Dies kann einige Minuten dauern, bitte übe dich etwas in Geduld.",
- "sideload-instructions-3": "Sobald die Installation abgeschlossen ist, kehrt das Telefon zum Hauptbildschirm zurück.",
- "sideload-instructions-4": "Erst dann kannst du auf Next
klicken.",
- "sign-up-free": "Kostenlos registrieren",
- "skip": "Überspringen",
- "start": "Start",
- "this-might-take-some-time-please-be-patient": "Das könnte einige Zeit dauern, bitte habe etwas Geduld",
- "unlocking-instructions-1": "Dein Telefon fragt nach dem Entsperren. Wähle unlock bootloader
aus, indem du Lautstärke lauter und Lautstärke leiser zum Navigieren benutzt.",
- "unlocking-instructions-2": "Wenn sich das Gerät nicht automatisch neu startet, starte es neu.",
- "unlocking-instructions-3": "Da das Gerät vollständig zurückgesetzt wird, musst du USB-Debugging erneut aktivieren.",
- "unlocking-instructions-4": "Überspringe die Einrichtung auf dem Telefon und klicke auf Weiter",
- "very-dissatisfied": "Sehr unzufrieden",
- "very-satisfied": "Sehr zufrieden",
- "format-device-instructions-7": "7. Auf den Rückwärts
-Pfeil tippen, dann auf Weiter
",
- "locking-instructions-3": "Dann auf Weiter tippen",
- "unlocking-instructions-2-a": "Das Gerät wird neu starten. Warte, bis der Bootloader-Bildschirm erneut erscheint, bevor du zum nächsten Schritt übergehst.",
- "unlocking-instructions-5": "Dann auf Weiter tippen",
- "unlocking-instructions-1-a": "Benutze den Ausschalten zum Bestätigen.",
- "android-version-not-supported-title": "Ihre Android-Version {{android-version}}
wird nicht unterstützt",
- "android-version-not-supported": "Android-Version veraltet",
- "android-version-not-supported-instructions": "Aktualisieren Sie Ihr System auf die erforderliche Minimal-Version {{android-version-required}}
",
- "go-to-apply-update-instructions-4": "Bemerkung: Für den nächsten Schritt muss sich dein Browser wahrscheinlich mit dem Telefon neu verbinden. Wenn ein Fenster aufscheint, wähle bitte dein Gerät aus der Liste aus.",
- "installing": "Wird installiert"
+ "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Beispiel 1: Bevor du /e/OS Android 12 installierst, solltest du auf die neueste Standardversion von Android 12 aktualisieren.",
+ "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Beispiel 2: Oder wenn du /e/OS Android 11 installierst, stelle sicher, dass du vorher auf die neueste Standardversion von Android 11 aktualisierst.",
+ "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Beispiel 3: Ähnlich, wenn du /e/OS Android 11 installierst, sollte es die neueste Standardversion von Android 10 sein.",
+ "activate-developer-options": "Entwickleroptionen aktivieren",
+ "activate-developer-options-instructions-1": "1. Öffne das Einstellungsmenü und gib ‘Build’ in die Suchleiste ein.",
+ "activate-developer-options-instructions-2": "2. Auf dem nächsten Bildschirm finde ‘Build-Nummer’ und tippe 7 Mal darauf.",
+ "activate-usb-debugging": "USB-Debugging aktivieren",
+ "activate-usb-debugging-instructions-1": "1. Gehe zurück zum Einstellungsmenü und gib ‘USB-Debugging’ in die Suchleiste ein.",
+ "activate-usb-debugging-instructions-2": "2. Zu diesem Zeitpunkt solltest du im Bildschirm ‘Entwickleroptionen’ sein. Tippe nun auf ‘USB-Debugging’, um es zu aktivieren (bei einigen Geräten wird es ‘Android-Debugging’ genannt).",
+ "bootloader-to-recovery-manually": "Bootloader zu Recovery",
+ "bootloader-to-recovery-manually-instructions": "Jetzt werden wir dein Gerät im Recovery-Modus neu starten. Bitte folge den untenstehenden Schritten:",
+ "bootloader-to-recovery-manually-instructions-1": "1. Wähle im Bootloader Recovery Modus
aus, indem du Lautstärke lauter und Lautstärke leiser verwendest, um zu navigieren",
+ "bootloader-to-recovery-manually-instructions-2": "2. Drücke Ausschalten, um zu bestätigen",
+ "bootloader-to-recovery-manually-instructions-3": "3. Warte bis dein Telefon im Recovery-Modus neu startet",
+ "check-update-android-version": "Überprüfe und aktualisiere deine Android-Version",
+ "check-update-android-version-caution": "Vorsicht: Bevor du mit der Installation fortfährst, vergewissere dich, ob die neueste Android-Firmware für dein Gerät verfügbar ist.",
+ "connect": "Verbinden",
+ "connect-bootloader": "Bootloader-Verbindung",
+ "connect-bootloader-instructions-1": "Dein Telefon wird jetzt im Bootloader
-Modus neu starten.",
+ "connect-bootloader-instructions-2": "Wenn dein Telefon eingeschaltet ist, verbinde es im Bootloader
-Modus, indem du auf die untenstehende Schaltfläche tippst.",
+ "connect-your-phone": "Verbinde dein Telefon",
+ "connect-your-phone-instructions": "Verbinde dein Telefon mit einem USB-Kabel mit deinem Computer. Wir erkennen dein Telefon automatisch, um /e/OS zu installieren.",
+ "connect-your-phone-instructions-notes": "Hinweis: ‘USB-Debugging’ ist erforderlich, damit die automatische Geräteerkennung funktioniert. Wenn du es noch nicht aktiviert hast, helfen wir dir in den nächsten Schritten.",
+ "device-detection": "Geräteerkennung",
+ "device-detection-detected": "Ein Gerät wurde erkannt.",
+ "device-detection-instructions-1": "Wir verbinden jetzt dein Telefon mit dem Browser. Wenn dieses Pop-up erscheint, wähle dein Telefon aus der Liste aus.",
+ "device-detection-instructions-2": "Es wird ein Pop-up-Fenster auf deinem Telefon erscheinen. Du musst Immer von diesem Computer zulassen
auswählen, bevor du auf OK drückst.",
+ "device-detection-instructions-3": "Tippe auf die untenstehende Schaltfläche, um die Verbindung zu starten.",
+ "device-model-not-supported": "Gerätemodell nicht unterstützt",
+ "device-model-not-supported-instructions": "Du kannst /e/OS nicht mit diesem Programm installieren",
+ "device-model-not-supported-title": "Dein Telefon {{product-name}} ist nicht kompatibel",
+ "dissatisfied": "Unzufrieden",
+ "donate": "Spenden",
+ "enable-usb-file-transfer": "USB-Dateiübertragung aktivieren",
+ "enable-usb-file-transfer-instructions-1": "Immer noch in den ‘Entwickleroptionen’, scrolle nach unten, um ‘Standard-USB-Konfiguration’ zu finden und tippe darauf.",
+ "enable-usb-file-transfer-instructions-2": "Wähle jetzt die Option ‘Dateiübertragung’ (bei einigen Geräten wird es ‘MTP-Modus (Media Transfer Protocol)’ genannt).",
+ "format-device": "Gerät formatieren",
+ "format-device-instructions-1": "1. Wähle Werkseinstellung zurücksetzen
",
+ "format-device-instructions-2": "2. Wähle die Option Daten formatieren / Werkseinstellung zurücksetzen
",
+ "format-device-instructions-3": "3. Der nächste Bildschirm zeigt eine Warnung an, dass diese Aktion nicht rückgängig gemacht werden kann",
+ "format-device-instructions-4": "4. Wähle Daten formatieren
, um fortzufahren",
+ "format-device-instructions-5": "5. Bitte warten, der Formatierungsprozess wird abgeschlossen",
+ "format-device-instructions-6": "6. Der Bildschirm kehrt jetzt zum Werkseinstellungsbildschirm zurück",
+ "go-to-apply-update": "Fast geschafft!",
+ "go-to-apply-update-instructions-1": "1. Wähle Aktualisierung anwenden
",
+ "go-to-apply-update-instructions-2": "2. und dann Aktualisierung von adb anwenden
",
+ "go-to-apply-update-instructions-3": "3. Das Gerät befindet sich jetzt im Sideload-Modus und du bist bereit für den nächsten Schritt.",
+ "help": "Hilfe",
+ "help-us-improve-the-tool": "Hilf uns, das Programm zu verbessern",
+ "help-us-improve-the-tool-instructions-1": "Bitte bewerte deine Erfahrung mit dem /e/OS Installer.",
+ "help-us-improve-the-tool-instructions-2": "Hast du irgendwelche Idee dazu, wie wir dieses Programm verbessern können?",
+ "i-already-have-an-account": "Ich habe bereits ein Konto",
+ "i-m-ready": "Ich bin bereit!",
+ "installation-complete": "Die Installation ist abgeschlossen!",
+ "installation-complete-instructions-1": "Glückwunsch! Während dein Telefon hochfährt, solltest du das untenstehende Logo sehen. Das kann eine Weile dauern, bitte habe etwas Geduld.",
+ "installation-complete-instructions-2": "Tipp: Folge den Anweisungen auf deinem Telefon, um dein Gerät einzurichten. Du kannst jetzt deine Dateien zurück auf dein Telefon übertragen.",
+ "let-s-get-started": "Los geht's",
+ "let-s-get-started-instruction-1": "Der komplette Installationsprozess dauert etwa 1 Stunde. Bring etwas Geduld mit!",
+ "let-s-get-started-instruction-2": "Du brauchst mindestens 6 GB freien Speicherplatz auf deinem Computer, um /e/OS herunterzuladen und zu installieren. Stelle sicher, dass du genügend freien Speicherplatz hast.",
+ "let-s-get-started-instruction-3": "Bevor du /e/OS installierst, stelle sicher, dass dein Telefon mindestens 50% Akku hat.",
+ "let-s-get-started-instruction-4": "Alle Daten werden während der Installation von deinem Smartphone gelöscht, daher empfehlen wir, deine Daten vorher zu sichern.",
+ "let-s-get-started-instruction-5": "Ein funktionierendes USB-Datenkabel ist erforderlich. Stromkabel übertragen keine Daten und funktionieren nicht! Wir empfehlen USB 3.x oder neuer.",
+ "let-s-get-started-instruction-title-1": "1. Nimm dir etwas freie Zeit",
+ "let-s-get-started-instruction-title-2": "2. Mach Platz auf deiner Festplatte",
+ "let-s-get-started-instruction-title-3": "3. Lade dein Telefon auf",
+ "let-s-get-started-instruction-title-4": "4. Sichere deine Daten",
+ "let-s-get-started-instruction-title-5": "5. Hol dir ein USB-Datenkabel",
+ "locking": "Sperren",
+ "locking-instructions-1": "Dein Telefon fragt nach einer Sperre. Wähle lock bootloader
",
+ "locking-instructions-2": "Wenn sich das Gerät nicht automatisch neu startet, starte es neu",
+ "murena-workspace-account": "Murena Workspace-Konto",
+ "murena-workspace-account-instructions": "Sichere deine Daten und synchronisiere dieses Gerät mit deinem persönlichen Murena Workspace-Konto. 1 GB sind kostenlos, es gibt auch ein Bezahl-Abo für mehr Speicherplatz.",
+ "navigator-detection": "Browser-Erkennung",
+ "navigator-not-supported": "Dein Browser wird nicht unterstützt",
+ "navigator-not-supported-instructions": "Du kannst die folgenden Browser verwenden",
+ "neutral": "Neutral",
+ "next": "Weiter",
+ "ready-to-install-e-os": "Du bist jetzt bereit, /e/OS zu installieren.",
+ "recovery-to-bootloader": "Recovery zu Bootloader",
+ "recovery-to-bootloader-instructions": "Im Hauptmenü",
+ "recovery-to-bootloader-instructions-1": "1. Wähle Erweitert
",
+ "recovery-to-bootloader-instructions-2": "2. Wähle Reboot to bootloader
",
+ "satisfied": "Zufrieden",
+ "send-to-e-team": "An das Murena Team senden",
+ "sideload": "Installation läuft",
+ "sideload-instructions-1": "Der Bildschirm zeigt den Fortschritt an … ",
+ "sideload-instructions-2": "Dies kann einige Minuten dauern, bitte übe dich etwas in Geduld.",
+ "sideload-instructions-3": "Sobald die Installation abgeschlossen ist, kehrt das Telefon zum Hauptbildschirm zurück.",
+ "sideload-instructions-4": "Erst dann kannst du auf Next
klicken.",
+ "sign-up-free": "Kostenlos registrieren",
+ "skip": "Überspringen",
+ "start": "Start",
+ "this-might-take-some-time-please-be-patient": "Das könnte einige Zeit dauern, bitte habe etwas Geduld",
+ "unlocking-instructions-1": "Dein Telefon fragt nach dem Entsperren. Wähle unlock bootloader
aus, indem du Lautstärke lauter und Lautstärke leiser zum Navigieren benutzt.",
+ "unlocking-instructions-2": "Wenn sich das Gerät nicht automatisch neu startet, starte es neu.",
+ "unlocking-instructions-3": "Da das Gerät vollständig zurückgesetzt wird, musst du USB-Debugging erneut aktivieren.",
+ "unlocking-instructions-4": "Überspringe die Einrichtung auf dem Telefon und klicke auf Weiter",
+ "very-dissatisfied": "Sehr unzufrieden",
+ "very-satisfied": "Sehr zufrieden",
+ "format-device-instructions-7": "7. Auf den Rückwärts
-Pfeil tippen, dann auf Weiter
",
+ "locking-instructions-3": "Dann auf Weiter tippen",
+ "unlocking-instructions-2-a": "Das Gerät wird neu starten. Warte, bis der Bootloader-Bildschirm erneut erscheint, bevor du zum nächsten Schritt übergehst.",
+ "unlocking-instructions-5": "Dann auf Weiter tippen",
+ "unlocking-instructions-1-a": "Benutze den Ausschalten zum Bestätigen.",
+ "android-version-not-supported-title": "Ihre Android-Version {{android-version}}
wird nicht unterstützt",
+ "android-version-not-supported": "Android-Version veraltet",
+ "android-version-not-supported-instructions": "Aktualisieren Sie Ihr System auf die erforderliche Minimal-Version {{android-version-required}}
",
+ "go-to-apply-update-instructions-4": "Bemerkung: Für den nächsten Schritt muss sich dein Browser wahrscheinlich mit dem Telefon neu verbinden. Wenn ein Fenster aufscheint, wähle bitte dein Gerät aus der Liste aus.",
+ "installing": "Wird installiert"
}
diff --git a/app/public/assets/languages/en.json b/app/public/assets/languages/en.json
index 905caaa94754f186678e0cf69106b1fe5bdf68d4..4f946b802a74c3a0a8491d1b95ab5930829e2c55 100644
--- a/app/public/assets/languages/en.json
+++ b/app/public/assets/languages/en.json
@@ -1,114 +1,114 @@
{
- "_err_01": "Error",
- "_err_02": "Your browser does not support Web USB",
- "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12",
- "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11",
- "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10",
- "activate-developer-options": "Activate Developer options",
- "activate-developer-options-instructions-1": "1. Open the settings menu and type ‘build’ in the search bar.",
- "activate-developer-options-instructions-2": "2. On the next screen, find ‘Build number’ and tap 7 times on it.",
- "activate-oem-unlock": "OEM Unlock",
- "activate-oem-unlock-instruction": "If you have not already done so, unlock the OEM function",
- "activate-usb-debugging": "Activate USB Debugging",
- "activate-usb-debugging-instructions-1": "1. Go back to the settings menu and type ‘USB debugging’ in the search bar.",
- "activate-usb-debugging-instructions-2": "2. At this point you should be in the ‘Developer options screen’. Now tap on ’USB debugging’ to activate it (on some devices it is called ’Android Debugging’).",
- "android-version-not-supported": "Android version outdated",
- "android-version-not-supported-instructions": "Update your system to the minimum version required {{android-version-required}}
",
- "android-version-not-supported-title": "Your Android version {{android-version}}
is not supported",
- "bootloader-to-recovery-manually": "Bootloader to recovery",
- "bootloader-to-recovery-manually-instructions": "Now we will restart your device in Recovery mode. Please, follow the steps below:",
- "bootloader-to-recovery-manually-instructions-1": "1. In the bootloader, select Recovery Mode
by using Volume Up and Volume Down to navigate",
- "bootloader-to-recovery-manually-instructions-2": "2. Press Power to confirm",
- "bootloader-to-recovery-manually-instructions-3": "3. Wait for your phone to start in recovery",
- "check-update-android-version": "Check & update your Android version",
- "check-update-android-version-caution": "Caution: before proceeding with the installation, verify if the latest Android firmware is available for your device.",
- "connect": "Connect",
- "connect-bootloader": "Bootloader connection",
- "connect-bootloader-instructions-1": "Your phone will now reboot in bootloader
mode",
- "connect-bootloader-instructions-2": "When your phone is on, connect your phone in bootloader
mode by clicking on the button below",
- "connect-your-phone": "Connect your phone",
- "connect-your-phone-instructions": "Connect your phone to your computer with a USB cable. We will automatically detect your phone to install /e/OS.",
- "connect-your-phone-instructions-notes": "Note: ’USB debugging’ is required for automatic device detection to work. If you haven't enabled it yet, we will help you out in the next steps.",
- "device-detection": "Device detection",
- "device-detection-detected": "A device has been detected.",
- "device-detection-instructions-1": "We'll now connect your phone to the browser. When this pop-up appears, select your telephone from the list.",
- "device-detection-instructions-2": "A pop-up window will then appeared on your phone. You will have to check always allow from this computer
before pressing ok.",
- "device-detection-instructions-3": "Click on the button below to start the connection",
- "device-model-not-supported": "Device model not supported",
- "device-model-not-supported-instructions": "you can't install /e/OS using this tool",
- "device-model-not-supported-title": "Your phone {{product-name}} is not compatible",
- "dissatisfied": "Dissatisfied",
- "donate": "Donate",
- "enable-usb-file-transfer": "Enable USB file transfer",
- "enable-usb-file-transfer-instructions-1": "Still inside the ‘Developer options’, scroll down to find ’Default USB configuration’ and tap on it.",
- "enable-usb-file-transfer-instructions-2": "Now select the ’File Transfer’ option (on some devices it is called 'MTP mode (media transfer protocol)').",
- "format-device": "Format the device",
- "format-device-instructions-1": "1. Select Factory reset
",
- "format-device-instructions-2": "2. Select Format data / Factory reset
option",
- "format-device-instructions-3": "3. Next screen will display a warning that this action cannot be undone",
- "format-device-instructions-4": "4. Select Format data
to proceed",
- "format-device-instructions-5": "5. Wait the format process will complete",
- "format-device-instructions-6": "6. Display will now return to the Factory Reset screen",
- "format-device-instructions-7": "7. Press Back
arrow, and click Next
",
- "go-to-apply-update": "Almost there!",
- "go-to-apply-update-instructions-1": "1. Select Apply Update
.",
- "go-to-apply-update-instructions-2": "2. And then Apply update from adb
.",
- "go-to-apply-update-instructions-3": "3. The device is now in sideload mode, you're ready for the next step.",
- "go-to-apply-update-instructions-4": "Note: For the next step, your browser may need to reconnect your phone. If a pop-up window appears, select your phone from the list.",
- "help": "Help",
- "i-already-have-an-account": "I already have an account",
- "i-m-ready": "I'm ready !",
- "installation-complete": "The installation is complete!",
- "installation-complete-instructions-1": "Congrats! While your phone is booting, you should see the logo below. This takes time, please be patient.",
- "installation-complete-instructions-2": "Tip: follow the instructions on your phone to set up your device. You can now add your files back to your phone.",
- "installing": "Installing",
- "let-s-get-started": "Let's get started",
- "let-s-get-started-instruction-1": "The complete installation process requires around 1 hour. Be\n patient!",
- "let-s-get-started-instruction-2": "You'll need to have at least 6GB of free space in your computer to\n download and install /e/OS. Make sure you have enough free disk space.",
- "let-s-get-started-instruction-3": "Before installing /e/OS, ensure your phone has at least 50% battery",
- "let-s-get-started-instruction-4": "All data will be erased from your smartphone during the installation,\n so we recommend that you back up your data.",
- "let-s-get-started-instruction-5": "A working USB data cable is required. Power cables don't transfer date\n and will not work! We recommend USB 3.x or newer.",
- "let-s-get-started-instruction-title-1": "1. Free up some time",
- "let-s-get-started-instruction-title-2": "2. Free up some disk space",
- "let-s-get-started-instruction-title-3": "3. Charge your phone",
- "let-s-get-started-instruction-title-4": "4. Back up your data",
- "let-s-get-started-instruction-title-5": "5. Grab a USB data cable",
- "locking": "Locking",
- "locking-instructions-1": "The phone is asking for the bootloader to be locked. Select lock bootloader
",
- "locking-instructions-2": "The device will automatically reboot.",
- "locking-instructions-3": "Then click Next",
- "locking-instructions-4": "On the phone, press the start button.",
- "locking-instructions-1-teracube": "The phone is asking for the bootloader to be locked. Select lock bootloader
by using Volume Up button.",
- "locking-instructions-1-teracube-a": "Then click Next.",
- "murena-workspace-account": "Murena Workspace account",
- "murena-workspace-account-instructions": "Keep your data safe and sync this device with your personal Murena Workspace account. 1GB free and paid plans available for more storage.",
- "navigator-detection": "Navigator detection",
- "navigator-not-supported": "Your navigator is not supported",
- "navigator-not-supported-instructions": "You can use the following browsers",
- "neutral": "Neutral",
- "next": "Next",
- "ready-to-install-e-os": "You're now ready to install /e/OS.",
- "recovery-to-bootloader": "Recovery to Bootloader",
- "recovery-to-bootloader-instructions": "In the main menu",
- "recovery-to-bootloader-instructions-1": "1. Select Advanced
",
- "recovery-to-bootloader-instructions-2": "2. Select Reboot to bootloader
",
- "satisfied": "Satisfied",
- "send-to-e-team": "Send to Murena team",
- "sideload": "Installation in progress",
- "sideload-instructions-3": "Once the installation is finished, the phone returns to the main recovery screen.",
- "sign-up-free": "Sign up FREE",
- "skip": "Skip",
- "start": "Start",
- "this-might-take-some-time-please-be-patient": "This might take some time please be patient",
- "unlocking-instructions-1": "The phone is asking for the bootloader to be unlocked. Select unlock bootloader
by using Volume Up and Volume Down to navigate.",
- "unlocking-instructions-1-a": "Use the button Power to confirm.",
- "unlocking-instructions-1-b": "The phone is asking for the bootloader to be unlocked. Select unlock bootloader
by using Volume Up button.",
- "unlocking-instructions-2": "The device will automatically reboot.",
- "unlocking-instructions-2-a": "Wait until the bootloader screen is visible again before going to the next step",
- "unlocking-instructions-3": "Since the device resets completely, you will need to re-enable USB debugging.",
- "unlocking-instructions-4": "Pass the setup on the phone and click on next",
- "unlocking-instructions-1-teracube": "The phone is asking for the bootloader to be unlocked. Select unlock bootloader
by using Volume Up button.",
- "unlocking-instructions-1-teracube-a": "Then click Next.",
- "very-dissatisfied": "Very Dissatisfied",
- "very-satisfied": "Very Satisfied"
+ "_err_01": "Error",
+ "_err_02": "Your browser does not support Web USB",
+ "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12",
+ "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11",
+ "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10",
+ "activate-developer-options": "Activate Developer options",
+ "activate-developer-options-instructions-1": "1. Open the settings menu and type ‘build’ in the search bar.",
+ "activate-developer-options-instructions-2": "2. On the next screen, find ‘Build number’ and tap 7 times on it.",
+ "activate-oem-unlock": "OEM Unlock",
+ "activate-oem-unlock-instruction": "If you have not already done so, unlock the OEM function",
+ "activate-usb-debugging": "Activate USB Debugging",
+ "activate-usb-debugging-instructions-1": "1. Go back to the settings menu and type ‘USB debugging’ in the search bar.",
+ "activate-usb-debugging-instructions-2": "2. At this point you should be in the ‘Developer options screen’. Now tap on ’USB debugging’ to activate it (on some devices it is called ’Android Debugging’).",
+ "android-version-not-supported": "Android version outdated",
+ "android-version-not-supported-instructions": "Update your system to the minimum version required {{android-version-required}}
",
+ "android-version-not-supported-title": "Your Android version {{android-version}}
is not supported",
+ "bootloader-to-recovery-manually": "Bootloader to recovery",
+ "bootloader-to-recovery-manually-instructions": "Now we will restart your device in Recovery mode. Please, follow the steps below:",
+ "bootloader-to-recovery-manually-instructions-1": "1. In the bootloader, select Recovery Mode
by using Volume Up and Volume Down to navigate",
+ "bootloader-to-recovery-manually-instructions-2": "2. Press Power to confirm",
+ "bootloader-to-recovery-manually-instructions-3": "3. Wait for your phone to start in recovery",
+ "check-update-android-version": "Check & update your Android version",
+ "check-update-android-version-caution": "Caution: before proceeding with the installation, verify if the latest Android firmware is available for your device.",
+ "connect": "Connect",
+ "connect-bootloader": "Bootloader connection",
+ "connect-bootloader-instructions-1": "Your phone will now reboot in bootloader
mode",
+ "connect-bootloader-instructions-2": "When your phone is on, connect your phone in bootloader
mode by clicking on the button below",
+ "connect-your-phone": "Connect your phone",
+ "connect-your-phone-instructions": "Connect your phone to your computer with a USB cable. We will automatically detect your phone to install /e/OS.",
+ "connect-your-phone-instructions-notes": "Note: ’USB debugging’ is required for automatic device detection to work. If you haven't enabled it yet, we will help you out in the next steps.",
+ "device-detection": "Device detection",
+ "device-detection-detected": "A device has been detected.",
+ "device-detection-instructions-1": "We'll now connect your phone to the browser. When this pop-up appears, select your telephone from the list.",
+ "device-detection-instructions-2": "A pop-up window will then appeared on your phone. You will have to check always allow from this computer
before pressing ok.",
+ "device-detection-instructions-3": "Click on the button below to start the connection",
+ "device-model-not-supported": "Device model not supported",
+ "device-model-not-supported-instructions": "you can't install /e/OS using this tool",
+ "device-model-not-supported-title": "Your phone {{product-name}} is not compatible",
+ "dissatisfied": "Dissatisfied",
+ "donate": "Donate",
+ "enable-usb-file-transfer": "Enable USB file transfer",
+ "enable-usb-file-transfer-instructions-1": "Still inside the ‘Developer options’, scroll down to find ’Default USB configuration’ and tap on it.",
+ "enable-usb-file-transfer-instructions-2": "Now select the ’File Transfer’ option (on some devices it is called 'MTP mode (media transfer protocol)').",
+ "format-device": "Format the device",
+ "format-device-instructions-1": "1. Select Factory reset
",
+ "format-device-instructions-2": "2. Select Format data / Factory reset
option",
+ "format-device-instructions-3": "3. Next screen will display a warning that this action cannot be undone",
+ "format-device-instructions-4": "4. Select Format data
to proceed",
+ "format-device-instructions-5": "5. Wait the format process will complete",
+ "format-device-instructions-6": "6. Display will now return to the Factory Reset screen",
+ "format-device-instructions-7": "7. Press Back
arrow, and click Next
",
+ "go-to-apply-update": "Almost there!",
+ "go-to-apply-update-instructions-1": "1. Select Apply Update
.",
+ "go-to-apply-update-instructions-2": "2. And then Apply update from adb
.",
+ "go-to-apply-update-instructions-3": "3. The device is now in sideload mode, you're ready for the next step.",
+ "go-to-apply-update-instructions-4": "Note: For the next step, your browser may need to reconnect your phone. If a pop-up window appears, select your phone from the list.",
+ "help": "Help",
+ "i-already-have-an-account": "I already have an account",
+ "i-m-ready": "I'm ready !",
+ "installation-complete": "The installation is complete!",
+ "installation-complete-instructions-1": "Congrats! While your phone is booting, you should see the logo below. This takes time, please be patient.",
+ "installation-complete-instructions-2": "Tip: follow the instructions on your phone to set up your device. You can now add your files back to your phone.",
+ "installing": "Installing",
+ "let-s-get-started": "Let's get started",
+ "let-s-get-started-instruction-1": "The complete installation process requires around 1 hour. Be\n patient!",
+ "let-s-get-started-instruction-2": "You'll need to have at least 6GB of free space in your computer to\n download and install /e/OS. Make sure you have enough free disk space.",
+ "let-s-get-started-instruction-3": "Before installing /e/OS, ensure your phone has at least 50% battery",
+ "let-s-get-started-instruction-4": "All data will be erased from your smartphone during the installation,\n so we recommend that you back up your data.",
+ "let-s-get-started-instruction-5": "A working USB data cable is required. Power cables don't transfer date\n and will not work! We recommend USB 3.x or newer.",
+ "let-s-get-started-instruction-title-1": "1. Free up some time",
+ "let-s-get-started-instruction-title-2": "2. Free up some disk space",
+ "let-s-get-started-instruction-title-3": "3. Charge your phone",
+ "let-s-get-started-instruction-title-4": "4. Back up your data",
+ "let-s-get-started-instruction-title-5": "5. Grab a USB data cable",
+ "locking": "Locking",
+ "locking-instructions-1": "The phone is asking for the bootloader to be locked. Select lock bootloader
",
+ "locking-instructions-2": "The device will automatically reboot.",
+ "locking-instructions-3": "Then click Next",
+ "locking-instructions-4": "On the phone, press the start button.",
+ "locking-instructions-1-teracube": "The phone is asking for the bootloader to be locked. Select lock bootloader
by using Volume Up button.",
+ "locking-instructions-1-teracube-a": "Then click Next.",
+ "murena-workspace-account": "Murena Workspace account",
+ "murena-workspace-account-instructions": "Keep your data safe and sync this device with your personal Murena Workspace account. 1GB free and paid plans available for more storage.",
+ "navigator-detection": "Navigator detection",
+ "navigator-not-supported": "Your navigator is not supported",
+ "navigator-not-supported-instructions": "You can use the following browsers",
+ "neutral": "Neutral",
+ "next": "Next",
+ "ready-to-install-e-os": "You're now ready to install /e/OS.",
+ "recovery-to-bootloader": "Recovery to Bootloader",
+ "recovery-to-bootloader-instructions": "In the main menu",
+ "recovery-to-bootloader-instructions-1": "1. Select Advanced
",
+ "recovery-to-bootloader-instructions-2": "2. Select Reboot to bootloader
",
+ "satisfied": "Satisfied",
+ "send-to-e-team": "Send to Murena team",
+ "sideload": "Installation in progress",
+ "sideload-instructions-3": "Once the installation is finished, the phone returns to the main recovery screen.",
+ "sign-up-free": "Sign up FREE",
+ "skip": "Skip",
+ "start": "Start",
+ "this-might-take-some-time-please-be-patient": "This might take some time please be patient",
+ "unlocking-instructions-1": "The phone is asking for the bootloader to be unlocked. Select unlock bootloader
by using Volume Up and Volume Down to navigate.",
+ "unlocking-instructions-1-a": "Use the button Power to confirm.",
+ "unlocking-instructions-1-b": "The phone is asking for the bootloader to be unlocked. Select unlock bootloader
by using Volume Up button.",
+ "unlocking-instructions-2": "The device will automatically reboot.",
+ "unlocking-instructions-2-a": "Wait until the bootloader screen is visible again before going to the next step",
+ "unlocking-instructions-3": "Since the device resets completely, you will need to re-enable USB debugging.",
+ "unlocking-instructions-4": "Pass the setup on the phone and click on next",
+ "unlocking-instructions-1-teracube": "The phone is asking for the bootloader to be unlocked. Select unlock bootloader
by using Volume Up button.",
+ "unlocking-instructions-1-teracube-a": "Then click Next.",
+ "very-dissatisfied": "Very Dissatisfied",
+ "very-satisfied": "Very Satisfied"
}
diff --git a/app/public/assets/languages/es.json b/app/public/assets/languages/es.json
index e6a54f0051abc84ba812a8ba952d9521b59afb4c..ada7d854e2bc8807742a48e606ade670862e352c 100644
--- a/app/public/assets/languages/es.json
+++ b/app/public/assets/languages/es.json
@@ -1,110 +1,110 @@
{
- "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Ej 1: antes de instalar /e/OS Android 12, debes actualizar a la última versión stock de Android 12",
- "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Ej 2: o si estás instalando /e/OS Android 11, asegúrate de actualizar a la última versión stock de Android 11",
- "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Ej 3: similarmente, si estás instalando /e/OS Android 11, debes tener la última versión stock de Android 10",
- "activate-developer-options": "Activar opciones de desarrollador",
- "activate-developer-options-instructions-1": "1. Abre el menú de configuración y escribe 'versión' en la barra de búsqueda.",
- "activate-developer-options-instructions-2": "2. En la siguiente pantalla, busca 'Número de compilación' y toca 7 veces sobre él.",
- "activate-usb-debugging": "Activar depuración USB",
- "activate-usb-debugging-instructions-1": "1. Regresa al menú de configuración y escribe 'depuración USB' en la barra de búsqueda.",
- "activate-usb-debugging-instructions-2": "2. En este punto deberías estar en la pantalla 'Opciones de desarrollador'. Ahora toca en 'Depuración USB' para activarla (en algunos dispositivos se llama 'Depuración de Android').",
- "bootloader-to-recovery-manually": "Gestor de arranque a recovery",
- "bootloader-to-recovery-manually-instructions": "Ahora reiniciaremos tu dispositivo en modo Recovery. Por favor, sigue los siguientes pasos:",
- "bootloader-to-recovery-manually-instructions-1": "1. En el gestor de arranque, selecciona recovery usando Subir volumen y Bajar volumen para navegar",
- "bootloader-to-recovery-manually-instructions-2": "2. Presiona Encender para confirmar",
- "check-update-android-version": "Verifica y actualiza tu versión de Android",
- "check-update-android-version-caution": "Precaución: antes de proceder con la instalación, verifica si el último firmware de Android está disponible para tu dispositivo.",
- "connect": "Conectar",
- "connect-bootloader": "Conexión del gestor de arranque",
- "connect-bootloader-instructions-1": "Tu teléfono se reiniciará ahora en modo gestor de arranque
",
- "connect-bootloader-instructions-2": "Si tu teléfono esté encendido, conéctalo en modo gestor de arranque
tocando en el botón abajo",
- "connect-your-phone": "Conecta tu teléfono",
- "connect-your-phone-instructions": "Conecta el teléfono a tu computadora con un cable USB. Detectaremos tu teléfono automáticamente para instalar /e/OS.",
- "connect-your-phone-instructions-notes": "Nota: la 'depuración USB' se requiere para que la detección automática funcione. Si aún no la has habilitado, te ayudaremos en los siguientes pasos.",
- "device-detection": "Detección del dispositivo",
- "device-detection-detected": "Se ha detectado un dispositivo.",
- "device-detection-instructions-1": "Ahora conectaremos tu teléfono al navegador. Cuando aparezca esta ventana, selecciona tu teléfono de la lista.",
- "device-detection-instructions-2": "Aparecerá una ventana emergente en tu teléfono. Marca siempre permitir desde esta computadora
antes de presionar OK.",
- "device-detection-instructions-3": "Toca el botón de abajo para iniciar la conexión",
- "device-model-not-supported": "Dispositivo no compatible",
- "device-model-not-supported-instructions": "no puedes instalar /e/OS usando esta herramienta",
- "device-model-not-supported-title": "Tu teléfono {{product-name}} no es compatible",
- "dissatisfied": "Insatisfecho",
- "donate": "Donar",
- "enable-usb-file-transfer": "Activar transferencia de archivos USB",
- "enable-usb-file-transfer-instructions-1": "Dentro de 'Opciones de desarrollador', desliza hacia abajo hasta encontrar 'Configuración USB predeterminada' y tócala.",
- "enable-usb-file-transfer-instructions-2": "Ahora selecciona la opción 'Transferencia de archivos' (también llamada 'modo MTP (protocolo de transferencia de medios)').",
- "format-device": "Formatear dispositivo",
- "format-device-instructions-1": "1. Selecciona Reinicio de fábrica
",
- "format-device-instructions-2": "2. Selecciona Formatear datos / Reinicio de fábrica
",
- "format-device-instructions-3": "3. La siguiente pantalla mostrará una advertencia que esta acción no se puede deshacer",
- "format-device-instructions-4": "4. Selecciona Formatear datos
para continuar",
- "format-device-instructions-5": "5. Espera que finalice el proceso de formateo",
- "format-device-instructions-6": "6. La pantalla ahora volverá a la página de Reinicio de fábrica",
- "go-to-apply-update": "¡Casi terminas!",
- "go-to-apply-update-instructions-1": "1. Selecciona Aplicar actualización
.",
- "go-to-apply-update-instructions-2": "2. Y luego Aplicar actualización desde adb
.",
- "go-to-apply-update-instructions-3": "3. El dispositivo ahora está en modo sideload, listo para el siguiente paso.",
- "help": "Ayuda",
- "help-us-improve-the-tool": "Ayúdanos a mejorar esta herramienta",
- "help-us-improve-the-tool-instructions-1": "Por favor, califica tu experiencia con el /e/OS Installer.",
- "help-us-improve-the-tool-instructions-2": "¿Tienes sugerencias cómo podríamos mejorar este software?",
- "i-already-have-an-account": "Ya tengo una cuenta",
- "i-m-ready": "¡Estoy listo!",
- "installation-complete": "¡La instalación está completa!",
- "installation-complete-instructions-1": "¡Felicidades! Mientras tu teléfono se inicia, deberías ver el siguiente logo. Esto tarda un poco, ten paciencia.",
- "installation-complete-instructions-2": "Consejo: sigue las instrucciones en tu teléfono para configurarlo. Ahora puedes volver a agregar tus archivos al teléfono.",
- "let-s-get-started": "Empecemos",
- "let-s-get-started-instruction-1": "El proceso completo de instalación tarda alrededor de 1 hora. ¡Ten \npaciencia!",
- "let-s-get-started-instruction-2": "Necesitarás al menos 6GB de espacio libre en tu computadora para descargar e instalar /e/OS. Asegúrate de tener suficiente espacio libre en tu disco.",
- "let-s-get-started-instruction-3": "Antes de instalar /e/OS, asegúrate que tu teléfono este cargado al menos 50%",
- "let-s-get-started-instruction-4": "Todos los datos en tu teléfono se borrarán durante la instalación, por lo que te recomendamos que hagas una copia de seguridad.",
- "let-s-get-started-instruction-5": "Se requiere un cable USB en buen estado. ¡Los cables de recargue no transfieren datos y no funcionarán! Recomendamos USB 3.x o más nuevo.",
- "let-s-get-started-instruction-title-1": "1. Tómate algo de tiempo",
- "let-s-get-started-instruction-title-2": "2. Libera espacio en tu disco",
- "let-s-get-started-instruction-title-3": "3. Carga tu teléfono",
- "let-s-get-started-instruction-title-4": "4. Haz una copia de seguridad de tus datos",
- "let-s-get-started-instruction-title-5": "5. Toma un cable de datos USB",
- "locking": "Bloqueo",
- "locking-instructions-1": "Tu teléfono está pidiendo un desbloqueo. Selecciona lock bootloader
",
- "locking-instructions-2": "Si tu dispositivo no se reinicia automáticamente, reinícialo",
- "murena-workspace-account": "Cuenta Murena Workspace",
- "murena-workspace-account-instructions": "Mantén tus datos seguros y sincroniza este dispositivo con tu cuenta personal de Murena Workspace. 1GB gratis y planes de pago disponibles para más almacenamiento.",
- "navigator-detection": "Detectando el navegador",
- "navigator-not-supported": "Tu navegador no es compatible",
- "navigator-not-supported-instructions": "Puedes usar los siguientes navegadores",
- "neutral": "Neutral",
- "next": "Siguiente",
- "ready-to-install-e-os": "Estás listo para instalar /e/OS.",
- "recovery-to-bootloader": "Recovery
a Gestor de arranque
",
- "recovery-to-bootloader-instructions": "En el menú principal",
- "recovery-to-bootloader-instructions-1": "1. Selecciona Avanzado
",
- "recovery-to-bootloader-instructions-2": "2. Selecciona Reiniciar en gestor de arranque
",
- "satisfied": "Satisfecho",
- "send-to-e-team": "Enviar al equipo Murena",
- "sideload": "Instalación en progreso",
- "sideload-instructions-1": "La pantalla mostrará el progreso... ",
- "sideload-instructions-2": "Esto puede tardar varios minutos, dale algo de tiempo.",
- "sideload-instructions-3": "Una vez que la instalación concluya, el teléfono regresará a la pantalla principal.",
- "sideload-instructions-4": "Solo entonces puedes hacer clic en Siguiente
.",
- "sign-up-free": "Regístrate GRATIS",
- "skip": "Saltar",
- "start": "Comenzar",
- "this-might-take-some-time-please-be-patient": "Esto puede tomar algo de tiempo, ten paciencia",
- "unlocking-instructions-1": "El teléfono solicita un desbloqueo. Selecciona desbloquear gestor de arranque
usando Volumen arriba y Volumen abajo para navegar.",
- "unlocking-instructions-2": "Si tu dispositivo no se reinicia automáticamente, reinícialo.",
- "unlocking-instructions-3": "Como el dispositivo se reinicia completamente, necesitarás reactivar la depuración USB.",
- "unlocking-instructions-4": "Después de la configuración haz clic en siguiente",
- "very-dissatisfied": "Muy insatisfecho",
- "very-satisfied": "Muy satisfecho",
- "format-device-instructions-7": "7. Pulsa la flecha Atrás
y haz clic en Siguiente
",
- "locking-instructions-3": "A continuación, haz clic en Siguiente",
- "android-version-not-supported": "Versión de Android no actualizada",
- "android-version-not-supported-instructions": "Actualiza tu sistema a la versión mínima requerida {{android-version-required}}
",
- "android-version-not-supported-title": "Tu versión de Android {{android-version}}
no es compatible",
- "bootloader-to-recovery-manually-instructions-3": "3. Espera que tu teléfono se reinicie en modo recuperación",
- "go-to-apply-update-instructions-4": "Nota: Para el siguiente paso, es posible que tu navegador necesite volver a conectarse con tu teléfono. Si aparece una ventana emergente, selecciona tu teléfono de la lista.",
- "installing": "Instalando",
- "unlocking-instructions-1-a": "Usa el botón Encender para confirmar.",
- "unlocking-instructions-2-a": "Tu dispositivo se reiniciará. Espera hasta que la pantalla del gestor de arranque sea visible otra vez antes de ir al siguiente paso"
+ "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Ej 1: antes de instalar /e/OS Android 12, debes actualizar a la última versión stock de Android 12",
+ "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Ej 2: o si estás instalando /e/OS Android 11, asegúrate de actualizar a la última versión stock de Android 11",
+ "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Ej 3: similarmente, si estás instalando /e/OS Android 11, debes tener la última versión stock de Android 10",
+ "activate-developer-options": "Activar opciones de desarrollador",
+ "activate-developer-options-instructions-1": "1. Abre el menú de configuración y escribe 'versión' en la barra de búsqueda.",
+ "activate-developer-options-instructions-2": "2. En la siguiente pantalla, busca 'Número de compilación' y toca 7 veces sobre él.",
+ "activate-usb-debugging": "Activar depuración USB",
+ "activate-usb-debugging-instructions-1": "1. Regresa al menú de configuración y escribe 'depuración USB' en la barra de búsqueda.",
+ "activate-usb-debugging-instructions-2": "2. En este punto deberías estar en la pantalla 'Opciones de desarrollador'. Ahora toca en 'Depuración USB' para activarla (en algunos dispositivos se llama 'Depuración de Android').",
+ "bootloader-to-recovery-manually": "Gestor de arranque a recovery",
+ "bootloader-to-recovery-manually-instructions": "Ahora reiniciaremos tu dispositivo en modo Recovery. Por favor, sigue los siguientes pasos:",
+ "bootloader-to-recovery-manually-instructions-1": "1. En el gestor de arranque, selecciona recovery usando Subir volumen y Bajar volumen para navegar",
+ "bootloader-to-recovery-manually-instructions-2": "2. Presiona Encender para confirmar",
+ "check-update-android-version": "Verifica y actualiza tu versión de Android",
+ "check-update-android-version-caution": "Precaución: antes de proceder con la instalación, verifica si el último firmware de Android está disponible para tu dispositivo.",
+ "connect": "Conectar",
+ "connect-bootloader": "Conexión del gestor de arranque",
+ "connect-bootloader-instructions-1": "Tu teléfono se reiniciará ahora en modo gestor de arranque
",
+ "connect-bootloader-instructions-2": "Si tu teléfono esté encendido, conéctalo en modo gestor de arranque
tocando en el botón abajo",
+ "connect-your-phone": "Conecta tu teléfono",
+ "connect-your-phone-instructions": "Conecta el teléfono a tu computadora con un cable USB. Detectaremos tu teléfono automáticamente para instalar /e/OS.",
+ "connect-your-phone-instructions-notes": "Nota: la 'depuración USB' se requiere para que la detección automática funcione. Si aún no la has habilitado, te ayudaremos en los siguientes pasos.",
+ "device-detection": "Detección del dispositivo",
+ "device-detection-detected": "Se ha detectado un dispositivo.",
+ "device-detection-instructions-1": "Ahora conectaremos tu teléfono al navegador. Cuando aparezca esta ventana, selecciona tu teléfono de la lista.",
+ "device-detection-instructions-2": "Aparecerá una ventana emergente en tu teléfono. Marca siempre permitir desde esta computadora
antes de presionar OK.",
+ "device-detection-instructions-3": "Toca el botón de abajo para iniciar la conexión",
+ "device-model-not-supported": "Dispositivo no compatible",
+ "device-model-not-supported-instructions": "no puedes instalar /e/OS usando esta herramienta",
+ "device-model-not-supported-title": "Tu teléfono {{product-name}} no es compatible",
+ "dissatisfied": "Insatisfecho",
+ "donate": "Donar",
+ "enable-usb-file-transfer": "Activar transferencia de archivos USB",
+ "enable-usb-file-transfer-instructions-1": "Dentro de 'Opciones de desarrollador', desliza hacia abajo hasta encontrar 'Configuración USB predeterminada' y tócala.",
+ "enable-usb-file-transfer-instructions-2": "Ahora selecciona la opción 'Transferencia de archivos' (también llamada 'modo MTP (protocolo de transferencia de medios)').",
+ "format-device": "Formatear dispositivo",
+ "format-device-instructions-1": "1. Selecciona Reinicio de fábrica
",
+ "format-device-instructions-2": "2. Selecciona Formatear datos / Reinicio de fábrica
",
+ "format-device-instructions-3": "3. La siguiente pantalla mostrará una advertencia que esta acción no se puede deshacer",
+ "format-device-instructions-4": "4. Selecciona Formatear datos
para continuar",
+ "format-device-instructions-5": "5. Espera que finalice el proceso de formateo",
+ "format-device-instructions-6": "6. La pantalla ahora volverá a la página de Reinicio de fábrica",
+ "go-to-apply-update": "¡Casi terminas!",
+ "go-to-apply-update-instructions-1": "1. Selecciona Aplicar actualización
.",
+ "go-to-apply-update-instructions-2": "2. Y luego Aplicar actualización desde adb
.",
+ "go-to-apply-update-instructions-3": "3. El dispositivo ahora está en modo sideload, listo para el siguiente paso.",
+ "help": "Ayuda",
+ "help-us-improve-the-tool": "Ayúdanos a mejorar esta herramienta",
+ "help-us-improve-the-tool-instructions-1": "Por favor, califica tu experiencia con el /e/OS Installer.",
+ "help-us-improve-the-tool-instructions-2": "¿Tienes sugerencias cómo podríamos mejorar este software?",
+ "i-already-have-an-account": "Ya tengo una cuenta",
+ "i-m-ready": "¡Estoy listo!",
+ "installation-complete": "¡La instalación está completa!",
+ "installation-complete-instructions-1": "¡Felicidades! Mientras tu teléfono se inicia, deberías ver el siguiente logo. Esto tarda un poco, ten paciencia.",
+ "installation-complete-instructions-2": "Consejo: sigue las instrucciones en tu teléfono para configurarlo. Ahora puedes volver a agregar tus archivos al teléfono.",
+ "let-s-get-started": "Empecemos",
+ "let-s-get-started-instruction-1": "El proceso completo de instalación tarda alrededor de 1 hora. ¡Ten \npaciencia!",
+ "let-s-get-started-instruction-2": "Necesitarás al menos 6GB de espacio libre en tu computadora para descargar e instalar /e/OS. Asegúrate de tener suficiente espacio libre en tu disco.",
+ "let-s-get-started-instruction-3": "Antes de instalar /e/OS, asegúrate que tu teléfono este cargado al menos 50%",
+ "let-s-get-started-instruction-4": "Todos los datos en tu teléfono se borrarán durante la instalación, por lo que te recomendamos que hagas una copia de seguridad.",
+ "let-s-get-started-instruction-5": "Se requiere un cable USB en buen estado. ¡Los cables de recargue no transfieren datos y no funcionarán! Recomendamos USB 3.x o más nuevo.",
+ "let-s-get-started-instruction-title-1": "1. Tómate algo de tiempo",
+ "let-s-get-started-instruction-title-2": "2. Libera espacio en tu disco",
+ "let-s-get-started-instruction-title-3": "3. Carga tu teléfono",
+ "let-s-get-started-instruction-title-4": "4. Haz una copia de seguridad de tus datos",
+ "let-s-get-started-instruction-title-5": "5. Toma un cable de datos USB",
+ "locking": "Bloqueo",
+ "locking-instructions-1": "Tu teléfono está pidiendo un desbloqueo. Selecciona lock bootloader
",
+ "locking-instructions-2": "Si tu dispositivo no se reinicia automáticamente, reinícialo",
+ "murena-workspace-account": "Cuenta Murena Workspace",
+ "murena-workspace-account-instructions": "Mantén tus datos seguros y sincroniza este dispositivo con tu cuenta personal de Murena Workspace. 1GB gratis y planes de pago disponibles para más almacenamiento.",
+ "navigator-detection": "Detectando el navegador",
+ "navigator-not-supported": "Tu navegador no es compatible",
+ "navigator-not-supported-instructions": "Puedes usar los siguientes navegadores",
+ "neutral": "Neutral",
+ "next": "Siguiente",
+ "ready-to-install-e-os": "Estás listo para instalar /e/OS.",
+ "recovery-to-bootloader": "Recovery
a Gestor de arranque
",
+ "recovery-to-bootloader-instructions": "En el menú principal",
+ "recovery-to-bootloader-instructions-1": "1. Selecciona Avanzado
",
+ "recovery-to-bootloader-instructions-2": "2. Selecciona Reiniciar en gestor de arranque
",
+ "satisfied": "Satisfecho",
+ "send-to-e-team": "Enviar al equipo Murena",
+ "sideload": "Instalación en progreso",
+ "sideload-instructions-1": "La pantalla mostrará el progreso... ",
+ "sideload-instructions-2": "Esto puede tardar varios minutos, dale algo de tiempo.",
+ "sideload-instructions-3": "Una vez que la instalación concluya, el teléfono regresará a la pantalla principal.",
+ "sideload-instructions-4": "Solo entonces puedes hacer clic en Siguiente
.",
+ "sign-up-free": "Regístrate GRATIS",
+ "skip": "Saltar",
+ "start": "Comenzar",
+ "this-might-take-some-time-please-be-patient": "Esto puede tomar algo de tiempo, ten paciencia",
+ "unlocking-instructions-1": "El teléfono solicita un desbloqueo. Selecciona desbloquear gestor de arranque
usando Volumen arriba y Volumen abajo para navegar.",
+ "unlocking-instructions-2": "Si tu dispositivo no se reinicia automáticamente, reinícialo.",
+ "unlocking-instructions-3": "Como el dispositivo se reinicia completamente, necesitarás reactivar la depuración USB.",
+ "unlocking-instructions-4": "Después de la configuración haz clic en siguiente",
+ "very-dissatisfied": "Muy insatisfecho",
+ "very-satisfied": "Muy satisfecho",
+ "format-device-instructions-7": "7. Pulsa la flecha Atrás
y haz clic en Siguiente
",
+ "locking-instructions-3": "A continuación, haz clic en Siguiente",
+ "android-version-not-supported": "Versión de Android no actualizada",
+ "android-version-not-supported-instructions": "Actualiza tu sistema a la versión mínima requerida {{android-version-required}}
",
+ "android-version-not-supported-title": "Tu versión de Android {{android-version}}
no es compatible",
+ "bootloader-to-recovery-manually-instructions-3": "3. Espera que tu teléfono se reinicie en modo recuperación",
+ "go-to-apply-update-instructions-4": "Nota: Para el siguiente paso, es posible que tu navegador necesite volver a conectarse con tu teléfono. Si aparece una ventana emergente, selecciona tu teléfono de la lista.",
+ "installing": "Instalando",
+ "unlocking-instructions-1-a": "Usa el botón Encender para confirmar.",
+ "unlocking-instructions-2-a": "Tu dispositivo se reiniciará. Espera hasta que la pantalla del gestor de arranque sea visible otra vez antes de ir al siguiente paso"
}
diff --git a/app/public/assets/languages/fr.json b/app/public/assets/languages/fr.json
index d93a0dcfe08052549ea9d09c4c927066fcc61366..7cf0d56c2e6d97026388248b0c8ca56ef5fe62d5 100644
--- a/app/public/assets/languages/fr.json
+++ b/app/public/assets/languages/fr.json
@@ -1,110 +1,110 @@
{
- "_err_01": "Erreur",
- "_err_02": "Votre navigateur ne supporte pas Web USB",
- "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Ex 1 : avant d'installer /e/OS Android 12, vous devez mettre à jour vers la dernière version stock d'Android 12",
- "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Ex 2 : ou si vous installez /e/OS Android 11, assurez-vous de mettre à jour vers la dernière version stock d'Android 11",
- "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Ex 3 : de même, si vous installez /e/OS Android 11, il doit s'agir de la dernière version stock d'Android 10",
- "activate-developer-options": "Activer les options pour les développeurs",
- "activate-developer-options-instructions-1": "1. Ouvrez le menu des paramètres et tapez 'build' dans la barre de recherche.",
- "activate-developer-options-instructions-2": "2. Sur l'écran suivant, trouvez 'Numéro de build' et appuyez dessus 7 fois.",
- "activate-oem-unlock":"OEM unlock",
- "activate-oem-unlock-instruction":"Si ce n'est pas déjà le cas, déverrouillez la fonction OEM",
- "activate-usb-debugging": "Activer le débogage USB",
- "activate-usb-debugging-instructions-1": "Retournez au menu des paramètres et tapez 'débogage USB' dans la barre de recherche.",
- "activate-usb-debugging-instructions-2": "À ce stade, vous devriez être dans l'écran 'Options pour les développeurs'. Appuyez maintenant sur 'Débogage USB' pour l'activer (sur certains appareils, cela s'appelle 'Débogage Android').",
- "bootloader-to-recovery-manually": "Bootloader à recovery",
- "bootloader-to-recovery-manually-instructions": "Nous allons maintenant redémarrer votre appareil en mode Recovery. Veuillez suivre les étapes ci-dessous :",
- "bootloader-to-recovery-manually-instructions-1": "1. Dans le bootloader, sélectionnez recovery en utilisant Volume Haut et Volume Bas pour naviguer",
- "bootloader-to-recovery-manually-instructions-2": "2. Appuyez sur Power pour confirmer",
- "bootloader-to-recovery-manually-instructions-3": "3. Attendez que votre téléphone démarre en recovery",
- "check-update-android-version": "Vérifiez et mettez à jour votre version d'Android",
- "check-update-android-version-caution": "Attention : avant de procéder à l'installation, vérifiez si le dernier firmware Android est disponible pour votre appareil.",
- "connect": "Connecter",
- "connect-bootloader": "Connexion au bootloader",
- "connect-bootloader-instructions-1": "Votre téléphone va maintenant redémarrer en mode bootloader
",
- "connect-bootloader-instructions-2": "Lorsque votre téléphone est allumé, connectez-le en mode bootloader
en cliquant sur le bouton ci-dessous",
- "connect-your-phone": "Connectez votre téléphone",
- "connect-your-phone-instructions": "Connectez votre téléphone à votre ordinateur avec un câble USB. Nous détecterons automatiquement votre téléphone pour installer /e/OS.",
- "connect-your-phone-instructions-notes": "Remarque : le 'débogage USB' est requis pour que la détection automatique de l'appareil fonctionne. Si vous ne l'avez pas encore activé, nous vous aiderons dans les étapes suivantes.",
- "device-detection": "Détection de l'appareil",
- "device-detection-detected": "Un appareil a été détecté.",
- "device-detection-instructions-1": "Nous allons maintenant connecter votre téléphone au navigateur. Lorsque cette fenêtre contextuelle apparaît, sélectionnez votre téléphone dans la liste.",
- "device-detection-instructions-2": "Une fenêtre contextuelle apparaîtra ensuite sur votre téléphone. Vous devrez cocher toujours autoriser depuis cet ordinateur
avant d'appuyer sur OK.",
- "device-detection-instructions-3": "Cliquez sur le bouton ci-dessous pour commencer la connexion",
- "device-model-not-supported": "Modèle d'appareil non pris en charge",
- "device-model-not-supported-instructions": "vous ne pouvez pas installer /e/OS en utilisant cet outil",
- "device-model-not-supported-title": "Votre téléphone {{product-name}} n'est pas compatible",
- "dissatisfied": "Insatisfait",
- "donate": "Faire un don",
- "enable-usb-file-transfer": "Activer le transfert de fichiers USB",
- "enable-usb-file-transfer-instructions-1": "Toujours dans les 'Options pour les développeurs', faites défiler vers le bas pour trouver 'Configuration USB par défaut' et appuyez dessus.",
- "enable-usb-file-transfer-instructions-2": "Sélectionnez maintenant l'option 'Transfert de fichiers' (sur certains appareils, cela s'appelle 'mode MTP (Media Transfer Protocol)').",
- "format-device": "Formater l'appareil",
- "format-device-instructions-1": "1. Sélectionnez Réinitialisation d'usine",
- "format-device-instructions-2": "2. Sélectionnez l'option Formater les données / Réinitialisation d'usine",
- "format-device-instructions-3": "3. L'écran suivant affichera un avertissement que cette action ne peut pas être annulée",
- "format-device-instructions-4": "4. Sélectionnez Formater les données pour continuer ou Annuler si vous souhaitez revenir en arrière",
- "format-device-instructions-5": "5. Si vous avez sélectionné Formater les données, le processus de formatage se terminera",
- "format-device-instructions-6": "6. L'écran reviendra maintenant à la page Réinitialisation d'usine",
- "format-device-instructions-7": "7. Cliquez sur la fléche Back
, puis Next
",
- "go-to-apply-update": "Presque terminé !",
- "go-to-apply-update-instructions-1": "1. Sélectionnez Appliquer la mise à jour",
- "go-to-apply-update-instructions-2": "2. Appliquer la mise à jour depuis adb",
- "go-to-apply-update-instructions-3": "L'appareil est maintenant en mode sideload",
- "go-to-apply-update-instructions-4": "Note: Pour l'étape suivante, il se peut que votre navigateur doive reconnecter votre téléphone. Si une fenêtre contextuelle apparaît, sélectionnez votre téléphone dans la liste.",
- "help": "Aide",
- "i-already-have-an-account": "J'ai déjà un compte",
- "i-m-ready": "Je suis prêt !",
- "installation-complete": "L'installation est terminée !",
- "installation-complete-instructions-1": "Félicitations ! Pendant que votre téléphone démarre, vous devriez voir le logo ci-dessous. Cela prend du temps, soyez patient.",
- "installation-complete-instructions-2": "Astuce : suivez les instructions sur votre téléphone pour configurer votre appareil. Vous pouvez maintenant ajouter vos fichiers à nouveau sur votre téléphone.",
- "let-s-get-started": "Commençons",
- "let-s-get-started-instruction-1": "Le processus d'installation complet prend environ 1 heure. Soyez patient !",
- "let-s-get-started-instruction-2": "Vous aurez besoin d'au moins 6 Go d'espace libre sur votre ordinateur pour télécharger et installer /e/OS. Assurez-vous d'avoir suffisamment d'espace libre sur le disque.",
- "let-s-get-started-instruction-3": "Avant d'installer /e/OS, assurez-vous que votre téléphone a au moins 50 % de batterie",
- "let-s-get-started-instruction-4": "Toutes les données seront effacées de votre smartphone pendant l'installation, nous vous recommandons donc de sauvegarder vos données.",
- "let-s-get-started-instruction-5": "Un câble de données USB fonctionnel est requis. Les câbles d'alimentation ne transfèrent pas de données et ne fonctionneront pas ! Nous recommandons USB 3.x ou plus récent.",
- "let-s-get-started-instruction-title-1": "1. Libérez du temps",
- "let-s-get-started-instruction-title-2": "2. Libérez de l'espace disque",
- "let-s-get-started-instruction-title-3": "3. Chargez votre téléphone",
- "let-s-get-started-instruction-title-4": "4. Sauvegardez vos données",
- "let-s-get-started-instruction-title-5": "5. Prenez un câble de données USB",
- "locking": "Verrouillage",
- "locking-instructions-1": "Votre téléphone demande un verrouillage. Sélectionnez lock bootloader
",
- "locking-instructions-2": "L'appareil va redémarrer",
- "locking-instructions-3": "Cliquer sur suivant",
- "locking-instructions-4": "Sur le téléphone appuyez sur le bouton start",
- "locking-instructions-1-teracube": "Votre téléphone demande un verrouillage. Sélectionnez lock bootloader
en utilisant le bouton Volume Up.",
- "locking-instructions-1-teracube-a": "Ensuite cliquez sur Suivant.",
- "murena-workspace-account": "Compte Murena Workspace",
- "murena-workspace-account-instructions": "Gardez vos données en sécurité et synchronisez cet appareil avec votre compte personnel Murena Workspace. 1 Go gratuit et des plans payants disponibles pour plus de stockage.",
- "navigator-detection": "Détection du navigateur",
- "navigator-not-supported": "Votre navigateur n'est pas pris en charge",
- "navigator-not-supported-instructions": "Vous pouvez utiliser les navigateurs suivants",
- "neutral": "Neutre",
- "next": "Suivant",
- "ready-to-install-e-os": "Vous êtes maintenant prêt à installer /e/OS.",
- "recovery-to-bootloader": "Recovery
vers Bootloader
",
- "recovery-to-bootloader-instructions": "Sélectionnez Avancé",
- "recovery-to-bootloader-instructions-1": "1. Sélectionnez Advanced
",
- "recovery-to-bootloader-instructions-2": "2. Sélectionnez Reboot to bootloader
",
- "satisfied": "Satisfait",
- "send-to-e-team": "Envoyer à l'équipe Murena",
- "sideload": "Installation en cours",
- "sideload-instructions-3": "Une fois l'installation terminée, le téléphone revient à l'écran principal du recovery.",
- "sign-up-free": "Inscrivez-vous GRATUITEMENT",
- "skip": "Passer",
- "start": "Commencer",
- "this-might-take-some-time-please-be-patient": "Cela peut prendre du temps, veuillez être patient",
- "unlocking-instructions-1": "Votre téléphone demande un déverrouillage. Sélectionnez unlock bootloader
en utilisant les boutons Volume Up and Volume Down pour naviguer.",
- "unlocking-instructions-1-a": "Utiliser le bouton Power pour confirmer.",
- "unlocking-instructions-1-b": "Votre téléphone demade à être déverrouilé. Selectionner unlock bootloader
en utilisant le bouton Volume Up.",
- "unlocking-instructions-2": "L'appareil va redémarrer. Il devrait maintenant être déverrouillé.",
- "unlocking-instructions-2-a": "Attendez que l'écran du bootloader soir à nouveau visible avant d'aller à l'étape suivante.",
- "unlocking-instructions-3": "Comme l'appareil réinitialise complètement, vous devrez réactiver le débogage USB.",
- "unlocking-instructions-4": "Passez la configuration et cliquez sur suivant",
- "unlocking-instructions-1-teracube": "Votre téléphone demande un déverrouillage. Sélectionnez unlock bootloader
en utilisant le bouton Volume Up.",
- "unlocking-instructions-1-teracube-a": "Ensuite cliquez sur Suivant.",
- "very-dissatisfied": "Très insatisfait",
- "very-satisfied": "Très satisfait"
+ "_err_01": "Erreur",
+ "_err_02": "Votre navigateur ne supporte pas Web USB",
+ "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Ex 1 : avant d'installer /e/OS Android 12, vous devez mettre à jour vers la dernière version stock d'Android 12",
+ "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Ex 2 : ou si vous installez /e/OS Android 11, assurez-vous de mettre à jour vers la dernière version stock d'Android 11",
+ "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Ex 3 : de même, si vous installez /e/OS Android 11, il doit s'agir de la dernière version stock d'Android 10",
+ "activate-developer-options": "Activer les options pour les développeurs",
+ "activate-developer-options-instructions-1": "1. Ouvrez le menu des paramètres et tapez 'build' dans la barre de recherche.",
+ "activate-developer-options-instructions-2": "2. Sur l'écran suivant, trouvez 'Numéro de build' et appuyez dessus 7 fois.",
+ "activate-oem-unlock": "OEM unlock",
+ "activate-oem-unlock-instruction": "Si ce n'est pas déjà le cas, déverrouillez la fonction OEM",
+ "activate-usb-debugging": "Activer le débogage USB",
+ "activate-usb-debugging-instructions-1": "Retournez au menu des paramètres et tapez 'débogage USB' dans la barre de recherche.",
+ "activate-usb-debugging-instructions-2": "À ce stade, vous devriez être dans l'écran 'Options pour les développeurs'. Appuyez maintenant sur 'Débogage USB' pour l'activer (sur certains appareils, cela s'appelle 'Débogage Android').",
+ "bootloader-to-recovery-manually": "Bootloader à recovery",
+ "bootloader-to-recovery-manually-instructions": "Nous allons maintenant redémarrer votre appareil en mode Recovery. Veuillez suivre les étapes ci-dessous :",
+ "bootloader-to-recovery-manually-instructions-1": "1. Dans le bootloader, sélectionnez recovery en utilisant Volume Haut et Volume Bas pour naviguer",
+ "bootloader-to-recovery-manually-instructions-2": "2. Appuyez sur Power pour confirmer",
+ "bootloader-to-recovery-manually-instructions-3": "3. Attendez que votre téléphone démarre en recovery",
+ "check-update-android-version": "Vérifiez et mettez à jour votre version d'Android",
+ "check-update-android-version-caution": "Attention : avant de procéder à l'installation, vérifiez si le dernier firmware Android est disponible pour votre appareil.",
+ "connect": "Connecter",
+ "connect-bootloader": "Connexion au bootloader",
+ "connect-bootloader-instructions-1": "Votre téléphone va maintenant redémarrer en mode bootloader
",
+ "connect-bootloader-instructions-2": "Lorsque votre téléphone est allumé, connectez-le en mode bootloader
en cliquant sur le bouton ci-dessous",
+ "connect-your-phone": "Connectez votre téléphone",
+ "connect-your-phone-instructions": "Connectez votre téléphone à votre ordinateur avec un câble USB. Nous détecterons automatiquement votre téléphone pour installer /e/OS.",
+ "connect-your-phone-instructions-notes": "Remarque : le 'débogage USB' est requis pour que la détection automatique de l'appareil fonctionne. Si vous ne l'avez pas encore activé, nous vous aiderons dans les étapes suivantes.",
+ "device-detection": "Détection de l'appareil",
+ "device-detection-detected": "Un appareil a été détecté.",
+ "device-detection-instructions-1": "Nous allons maintenant connecter votre téléphone au navigateur. Lorsque cette fenêtre contextuelle apparaît, sélectionnez votre téléphone dans la liste.",
+ "device-detection-instructions-2": "Une fenêtre contextuelle apparaîtra ensuite sur votre téléphone. Vous devrez cocher toujours autoriser depuis cet ordinateur
avant d'appuyer sur OK.",
+ "device-detection-instructions-3": "Cliquez sur le bouton ci-dessous pour commencer la connexion",
+ "device-model-not-supported": "Modèle d'appareil non pris en charge",
+ "device-model-not-supported-instructions": "vous ne pouvez pas installer /e/OS en utilisant cet outil",
+ "device-model-not-supported-title": "Votre téléphone {{product-name}} n'est pas compatible",
+ "dissatisfied": "Insatisfait",
+ "donate": "Faire un don",
+ "enable-usb-file-transfer": "Activer le transfert de fichiers USB",
+ "enable-usb-file-transfer-instructions-1": "Toujours dans les 'Options pour les développeurs', faites défiler vers le bas pour trouver 'Configuration USB par défaut' et appuyez dessus.",
+ "enable-usb-file-transfer-instructions-2": "Sélectionnez maintenant l'option 'Transfert de fichiers' (sur certains appareils, cela s'appelle 'mode MTP (Media Transfer Protocol)').",
+ "format-device": "Formater l'appareil",
+ "format-device-instructions-1": "1. Sélectionnez Réinitialisation d'usine",
+ "format-device-instructions-2": "2. Sélectionnez l'option Formater les données / Réinitialisation d'usine",
+ "format-device-instructions-3": "3. L'écran suivant affichera un avertissement que cette action ne peut pas être annulée",
+ "format-device-instructions-4": "4. Sélectionnez Formater les données pour continuer ou Annuler si vous souhaitez revenir en arrière",
+ "format-device-instructions-5": "5. Si vous avez sélectionné Formater les données, le processus de formatage se terminera",
+ "format-device-instructions-6": "6. L'écran reviendra maintenant à la page Réinitialisation d'usine",
+ "format-device-instructions-7": "7. Cliquez sur la fléche Back
, puis Next
",
+ "go-to-apply-update": "Presque terminé !",
+ "go-to-apply-update-instructions-1": "1. Sélectionnez Appliquer la mise à jour",
+ "go-to-apply-update-instructions-2": "2. Appliquer la mise à jour depuis adb",
+ "go-to-apply-update-instructions-3": "L'appareil est maintenant en mode sideload",
+ "go-to-apply-update-instructions-4": "Note: Pour l'étape suivante, il se peut que votre navigateur doive reconnecter votre téléphone. Si une fenêtre contextuelle apparaît, sélectionnez votre téléphone dans la liste.",
+ "help": "Aide",
+ "i-already-have-an-account": "J'ai déjà un compte",
+ "i-m-ready": "Je suis prêt !",
+ "installation-complete": "L'installation est terminée !",
+ "installation-complete-instructions-1": "Félicitations ! Pendant que votre téléphone démarre, vous devriez voir le logo ci-dessous. Cela prend du temps, soyez patient.",
+ "installation-complete-instructions-2": "Astuce : suivez les instructions sur votre téléphone pour configurer votre appareil. Vous pouvez maintenant ajouter vos fichiers à nouveau sur votre téléphone.",
+ "let-s-get-started": "Commençons",
+ "let-s-get-started-instruction-1": "Le processus d'installation complet prend environ 1 heure. Soyez patient !",
+ "let-s-get-started-instruction-2": "Vous aurez besoin d'au moins 6 Go d'espace libre sur votre ordinateur pour télécharger et installer /e/OS. Assurez-vous d'avoir suffisamment d'espace libre sur le disque.",
+ "let-s-get-started-instruction-3": "Avant d'installer /e/OS, assurez-vous que votre téléphone a au moins 50 % de batterie",
+ "let-s-get-started-instruction-4": "Toutes les données seront effacées de votre smartphone pendant l'installation, nous vous recommandons donc de sauvegarder vos données.",
+ "let-s-get-started-instruction-5": "Un câble de données USB fonctionnel est requis. Les câbles d'alimentation ne transfèrent pas de données et ne fonctionneront pas ! Nous recommandons USB 3.x ou plus récent.",
+ "let-s-get-started-instruction-title-1": "1. Libérez du temps",
+ "let-s-get-started-instruction-title-2": "2. Libérez de l'espace disque",
+ "let-s-get-started-instruction-title-3": "3. Chargez votre téléphone",
+ "let-s-get-started-instruction-title-4": "4. Sauvegardez vos données",
+ "let-s-get-started-instruction-title-5": "5. Prenez un câble de données USB",
+ "locking": "Verrouillage",
+ "locking-instructions-1": "Votre téléphone demande un verrouillage. Sélectionnez lock bootloader
",
+ "locking-instructions-2": "L'appareil va redémarrer",
+ "locking-instructions-3": "Cliquer sur suivant",
+ "locking-instructions-4": "Sur le téléphone appuyez sur le bouton start",
+ "locking-instructions-1-teracube": "Votre téléphone demande un verrouillage. Sélectionnez lock bootloader
en utilisant le bouton Volume Up.",
+ "locking-instructions-1-teracube-a": "Ensuite cliquez sur Suivant.",
+ "murena-workspace-account": "Compte Murena Workspace",
+ "murena-workspace-account-instructions": "Gardez vos données en sécurité et synchronisez cet appareil avec votre compte personnel Murena Workspace. 1 Go gratuit et des plans payants disponibles pour plus de stockage.",
+ "navigator-detection": "Détection du navigateur",
+ "navigator-not-supported": "Votre navigateur n'est pas pris en charge",
+ "navigator-not-supported-instructions": "Vous pouvez utiliser les navigateurs suivants",
+ "neutral": "Neutre",
+ "next": "Suivant",
+ "ready-to-install-e-os": "Vous êtes maintenant prêt à installer /e/OS.",
+ "recovery-to-bootloader": "Recovery
vers Bootloader
",
+ "recovery-to-bootloader-instructions": "Sélectionnez Avancé",
+ "recovery-to-bootloader-instructions-1": "1. Sélectionnez Advanced
",
+ "recovery-to-bootloader-instructions-2": "2. Sélectionnez Reboot to bootloader
",
+ "satisfied": "Satisfait",
+ "send-to-e-team": "Envoyer à l'équipe Murena",
+ "sideload": "Installation en cours",
+ "sideload-instructions-3": "Une fois l'installation terminée, le téléphone revient à l'écran principal du recovery.",
+ "sign-up-free": "Inscrivez-vous GRATUITEMENT",
+ "skip": "Passer",
+ "start": "Commencer",
+ "this-might-take-some-time-please-be-patient": "Cela peut prendre du temps, veuillez être patient",
+ "unlocking-instructions-1": "Votre téléphone demande un déverrouillage. Sélectionnez unlock bootloader
en utilisant les boutons Volume Up and Volume Down pour naviguer.",
+ "unlocking-instructions-1-a": "Utiliser le bouton Power pour confirmer.",
+ "unlocking-instructions-1-b": "Votre téléphone demade à être déverrouilé. Selectionner unlock bootloader
en utilisant le bouton Volume Up.",
+ "unlocking-instructions-2": "L'appareil va redémarrer. Il devrait maintenant être déverrouillé.",
+ "unlocking-instructions-2-a": "Attendez que l'écran du bootloader soir à nouveau visible avant d'aller à l'étape suivante.",
+ "unlocking-instructions-3": "Comme l'appareil réinitialise complètement, vous devrez réactiver le débogage USB.",
+ "unlocking-instructions-4": "Passez la configuration et cliquez sur suivant",
+ "unlocking-instructions-1-teracube": "Votre téléphone demande un déverrouillage. Sélectionnez unlock bootloader
en utilisant le bouton Volume Up.",
+ "unlocking-instructions-1-teracube-a": "Ensuite cliquez sur Suivant.",
+ "very-dissatisfied": "Très insatisfait",
+ "very-satisfied": "Très satisfait"
}
diff --git a/app/public/assets/languages/is.json b/app/public/assets/languages/is.json
index 8c133e7402ae160a96c205617afd79ac5d13912a..9b11476ed0c5e85e4f36b71f452940e7d03be83d 100644
--- a/app/public/assets/languages/is.json
+++ b/app/public/assets/languages/is.json
@@ -1,75 +1,75 @@
{
- "activate-usb-debugging": "Virkjaðu USB-villuleit",
- "next": "Næsta",
- "ready-to-install-e-os": "Núna er allt tilbúið til uppsetningar á /e/OS.",
- "recovery-to-bootloader-instructions": "Í aðalvalmyndinni",
- "satisfied": "Ánægð/ur",
- "send-to-e-team": "Senda til Murena-teymisins",
- "sideload": "Uppsetning í gangi",
- "sign-up-free": "Skráðu þig ókeypis",
- "skip": "Sleppa",
- "start": "Byrja",
- "this-might-take-some-time-please-be-patient": "Þetta gæti tekið drjúga stund, sýndu þolinmæði",
- "very-dissatisfied": "Mjög óánægð/ur",
- "very-satisfied": "Mjög ánægð/ur",
- "bootloader-to-recovery-manually-instructions-2": "2. Ýttu á aflrofann til að staðfesta",
- "connect": "Tengjast",
- "connect-your-phone": "Tengdu símann þinn",
- "device-detection": "Greining tækis",
- "device-detection-detected": "Tæki hefur fundist.",
- "dissatisfied": "Óánægð/ur",
- "donate": "Styrkja",
- "enable-usb-file-transfer": "Virkjaðu USB-skráaflutning",
- "format-device": "Forsníða tækið",
- "format-device-instructions-1": "1. Veldu Núllstilla á verksmiðjustillingar
",
- "format-device-instructions-2": "2. Veldu Forsníða gögn / Núllstilla á verksmiðjustillingar
",
- "go-to-apply-update": "Næstum því búið!",
- "help": "Hjálp",
- "i-already-have-an-account": "Ég er nú þegar með notandaaðgang",
- "installation-complete": "Uppsetningunni er lokið!",
- "let-s-get-started": "Hefjumst handa",
- "let-s-get-started-instruction-title-1": "1. Taktu frá nokkurn tíma",
- "let-s-get-started-instruction-title-3": "3. Hafðu símann þinn vel hlaðinn",
- "let-s-get-started-instruction-title-4": "4. Taktu öryggisafrit af gögnunum þínum",
- "let-s-get-started-instruction-title-5": "5. Taktu USB-gagnakapal sem virkar",
- "locking": "Læsing",
- "murena-workspace-account": "Murena-skýjaaðgangur",
- "navigator-not-supported-instructions": "Þú getur notað eftirfarandi vafra",
- "neutral": "Hlutlaus",
- "let-s-get-started-instruction-title-2": "2. Losaðu um eitthvað diskapláss",
- "device-detection-instructions-3": "Smelltu á hnappinn hér fyrir neðan til að ræsa tenginguna",
- "device-model-not-supported": "Þessi tegund tækis er ekki studd",
- "device-model-not-supported-instructions": "Þú getur ekki sett /e/OS upp með þessu verkfæri",
- "device-model-not-supported-title": "{{product-name}} síminn þinn er ekki samhæfður",
- "enable-usb-file-transfer-instructions-1": "Á meðan enn er verið í forritarahamnum, skaltu skruna niður og velja 'Sjálfgefnar USB-stillingar / ’Default USB Configuration'.",
- "installation-complete-instructions-1": "Til hamingju! Á meðan síminn þinn er að ræsast ættirðu að sjá táknmerkið hér fyrir neðan. Þetta gæti tekið drjúga stund, sýndu þolinmæði.",
- "let-s-get-started-instruction-4": "Gögnum snjallsímans verður eytt við uppsetninguna,\nþannig að við mælum með því að þú takir öryggisafrit af gögnunum þínum.",
- "locking-instructions-3": "Smelltu síðan á 'Næsta'",
- "navigator-detection": "Greining á vafra",
- "navigator-not-supported": "Það er ekki stuðningur við vafrann þinn",
- "unlocking-instructions-4": "Slepptu uppsetningunni á símanum og smelltu á 'Næsta'",
- "unlocking-instructions-5": "Smelltu síðan á 'Næsta'",
- "activate-developer-options": "Virkjaðu 'Stillingar fyrir forritara",
- "activate-developer-options-instructions-1": "1. Opnaðu stillingavalmyndina og skrifaðu 'build' í leitarstikuna.",
- "activate-developer-options-instructions-2": "2. Á næsta skjá skaltu finna ‘Build number’ og banka 7 sinnum á það.",
- "activate-usb-debugging-instructions-1": "1. Farðu aftur í stillingavalmyndina og skrifaðu '‘USB debugging’' í leitarstikuna.",
- "check-update-android-version": "Athugaðu og uppfærðu Android-útgáfuna þína",
- "connect-bootloader-instructions-1": "Síminn þinn mun núna endurræsast í bootloader
-ræsistjóraham",
- "connect-your-phone-instructions": "Tengdu símann þinn við tölvuna með USB-kapli. Síminn þinn á að finnast sjálfvirkt svo hægt sé að setja upp /e/OS.",
- "enable-usb-file-transfer-instructions-2": "Veldu núna 'Skráaflutningur / File Transfer' (á sumum tækjum er þetta kallað 'MTP-hamur (media transfer protocol)').",
- "format-device-instructions-3": "3. Næsti skjár mun birta aðvörun um að ekki sé hægt að afturkalla við þessa aðgerð",
- "format-device-instructions-4": "4. Veldu Forsníða gögn
til að halda áfram",
- "format-device-instructions-5": "5. Bíddu eftir að forsníðingarferlinu ljúki",
- "go-to-apply-update-instructions-1": "1. Veldu Beita uppfærslu
.",
- "go-to-apply-update-instructions-2": "2. Og síðan Virkja uppfærslu frá ADB
.",
- "help-us-improve-the-tool": "Hjálpaðu okkur að endurbæta verkfærið",
- "help-us-improve-the-tool-instructions-1": "Gefðu reynslu þinni af /e/OS Installer einkunn.",
- "help-us-improve-the-tool-instructions-2": "Ertu með einhverjar hugmyndir um hvernig hægt sé að betrumbæta þennan hugbúnað?",
- "i-m-ready": "Ég er tilbúin/n!",
- "let-s-get-started-instruction-1": "Uppsetningarferlið tekur í heildina u.þ.b. 1 klukkustund.\nSýndu þolinmæði!",
- "recovery-to-bootloader-instructions-1": "1. Veldu Ítarlegt
",
- "recovery-to-bootloader-instructions-2": "2. Veldu að enduræsa inn í ræsistjórann
",
- "sideload-instructions-1": "Skjárinn mun sýna framvinduna... ",
- "sideload-instructions-2": "Þetta gæti tekið nokkrar mínútur, sýndu þolinmæði.",
- "sideload-instructions-4": "Aðeins þá geturðu smellt á Næsta
."
+ "activate-usb-debugging": "Virkjaðu USB-villuleit",
+ "next": "Næsta",
+ "ready-to-install-e-os": "Núna er allt tilbúið til uppsetningar á /e/OS.",
+ "recovery-to-bootloader-instructions": "Í aðalvalmyndinni",
+ "satisfied": "Ánægð/ur",
+ "send-to-e-team": "Senda til Murena-teymisins",
+ "sideload": "Uppsetning í gangi",
+ "sign-up-free": "Skráðu þig ókeypis",
+ "skip": "Sleppa",
+ "start": "Byrja",
+ "this-might-take-some-time-please-be-patient": "Þetta gæti tekið drjúga stund, sýndu þolinmæði",
+ "very-dissatisfied": "Mjög óánægð/ur",
+ "very-satisfied": "Mjög ánægð/ur",
+ "bootloader-to-recovery-manually-instructions-2": "2. Ýttu á aflrofann til að staðfesta",
+ "connect": "Tengjast",
+ "connect-your-phone": "Tengdu símann þinn",
+ "device-detection": "Greining tækis",
+ "device-detection-detected": "Tæki hefur fundist.",
+ "dissatisfied": "Óánægð/ur",
+ "donate": "Styrkja",
+ "enable-usb-file-transfer": "Virkjaðu USB-skráaflutning",
+ "format-device": "Forsníða tækið",
+ "format-device-instructions-1": "1. Veldu Núllstilla á verksmiðjustillingar
",
+ "format-device-instructions-2": "2. Veldu Forsníða gögn / Núllstilla á verksmiðjustillingar
",
+ "go-to-apply-update": "Næstum því búið!",
+ "help": "Hjálp",
+ "i-already-have-an-account": "Ég er nú þegar með notandaaðgang",
+ "installation-complete": "Uppsetningunni er lokið!",
+ "let-s-get-started": "Hefjumst handa",
+ "let-s-get-started-instruction-title-1": "1. Taktu frá nokkurn tíma",
+ "let-s-get-started-instruction-title-3": "3. Hafðu símann þinn vel hlaðinn",
+ "let-s-get-started-instruction-title-4": "4. Taktu öryggisafrit af gögnunum þínum",
+ "let-s-get-started-instruction-title-5": "5. Taktu USB-gagnakapal sem virkar",
+ "locking": "Læsing",
+ "murena-workspace-account": "Murena-skýjaaðgangur",
+ "navigator-not-supported-instructions": "Þú getur notað eftirfarandi vafra",
+ "neutral": "Hlutlaus",
+ "let-s-get-started-instruction-title-2": "2. Losaðu um eitthvað diskapláss",
+ "device-detection-instructions-3": "Smelltu á hnappinn hér fyrir neðan til að ræsa tenginguna",
+ "device-model-not-supported": "Þessi tegund tækis er ekki studd",
+ "device-model-not-supported-instructions": "Þú getur ekki sett /e/OS upp með þessu verkfæri",
+ "device-model-not-supported-title": "{{product-name}} síminn þinn er ekki samhæfður",
+ "enable-usb-file-transfer-instructions-1": "Á meðan enn er verið í forritarahamnum, skaltu skruna niður og velja 'Sjálfgefnar USB-stillingar / ’Default USB Configuration'.",
+ "installation-complete-instructions-1": "Til hamingju! Á meðan síminn þinn er að ræsast ættirðu að sjá táknmerkið hér fyrir neðan. Þetta gæti tekið drjúga stund, sýndu þolinmæði.",
+ "let-s-get-started-instruction-4": "Gögnum snjallsímans verður eytt við uppsetninguna,\nþannig að við mælum með því að þú takir öryggisafrit af gögnunum þínum.",
+ "locking-instructions-3": "Smelltu síðan á 'Næsta'",
+ "navigator-detection": "Greining á vafra",
+ "navigator-not-supported": "Það er ekki stuðningur við vafrann þinn",
+ "unlocking-instructions-4": "Slepptu uppsetningunni á símanum og smelltu á 'Næsta'",
+ "unlocking-instructions-5": "Smelltu síðan á 'Næsta'",
+ "activate-developer-options": "Virkjaðu 'Stillingar fyrir forritara",
+ "activate-developer-options-instructions-1": "1. Opnaðu stillingavalmyndina og skrifaðu 'build' í leitarstikuna.",
+ "activate-developer-options-instructions-2": "2. Á næsta skjá skaltu finna ‘Build number’ og banka 7 sinnum á það.",
+ "activate-usb-debugging-instructions-1": "1. Farðu aftur í stillingavalmyndina og skrifaðu '‘USB debugging’' í leitarstikuna.",
+ "check-update-android-version": "Athugaðu og uppfærðu Android-útgáfuna þína",
+ "connect-bootloader-instructions-1": "Síminn þinn mun núna endurræsast í bootloader
-ræsistjóraham",
+ "connect-your-phone-instructions": "Tengdu símann þinn við tölvuna með USB-kapli. Síminn þinn á að finnast sjálfvirkt svo hægt sé að setja upp /e/OS.",
+ "enable-usb-file-transfer-instructions-2": "Veldu núna 'Skráaflutningur / File Transfer' (á sumum tækjum er þetta kallað 'MTP-hamur (media transfer protocol)').",
+ "format-device-instructions-3": "3. Næsti skjár mun birta aðvörun um að ekki sé hægt að afturkalla við þessa aðgerð",
+ "format-device-instructions-4": "4. Veldu Forsníða gögn
til að halda áfram",
+ "format-device-instructions-5": "5. Bíddu eftir að forsníðingarferlinu ljúki",
+ "go-to-apply-update-instructions-1": "1. Veldu Beita uppfærslu
.",
+ "go-to-apply-update-instructions-2": "2. Og síðan Virkja uppfærslu frá ADB
.",
+ "help-us-improve-the-tool": "Hjálpaðu okkur að endurbæta verkfærið",
+ "help-us-improve-the-tool-instructions-1": "Gefðu reynslu þinni af /e/OS Installer einkunn.",
+ "help-us-improve-the-tool-instructions-2": "Ertu með einhverjar hugmyndir um hvernig hægt sé að betrumbæta þennan hugbúnað?",
+ "i-m-ready": "Ég er tilbúin/n!",
+ "let-s-get-started-instruction-1": "Uppsetningarferlið tekur í heildina u.þ.b. 1 klukkustund.\nSýndu þolinmæði!",
+ "recovery-to-bootloader-instructions-1": "1. Veldu Ítarlegt
",
+ "recovery-to-bootloader-instructions-2": "2. Veldu að enduræsa inn í ræsistjórann
",
+ "sideload-instructions-1": "Skjárinn mun sýna framvinduna... ",
+ "sideload-instructions-2": "Þetta gæti tekið nokkrar mínútur, sýndu þolinmæði.",
+ "sideload-instructions-4": "Aðeins þá geturðu smellt á Næsta
."
}
diff --git a/app/public/assets/languages/it.json b/app/public/assets/languages/it.json
index 42d4be026bebcb25b385829ad49b5187c2d5deb9..3fe4b27079487f427a07e5a3e6e4a4033e280e87 100644
--- a/app/public/assets/languages/it.json
+++ b/app/public/assets/languages/it.json
@@ -1,101 +1,101 @@
{
- "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Es 1: prima di installare /e/OS Android 12, dovresti aggiornare all'ultima versione di stock di Android 12",
- "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Es 2: o se stai installando /e/OS Android 11, assicurati di aggiornare all'ultima versione di stock di Android 11",
- "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Es 3: allo stesso modo, se stai installando /e/OS Android 11, dovrebbe essere l'ultima versione di stock di Android 10",
- "activate-developer-options": "Attiva le opzioni sviluppatore",
- "activate-developer-options-instructions-1": "1. Apri il menu delle impostazioni e digita ‘build’ nella barra di ricerca.",
- "activate-developer-options-instructions-2": "2. Nella schermata successiva, trova ‘Numero di build’ e tocca 7 volte su di esso.",
- "activate-usb-debugging": "Attiva il debug USB",
- "activate-usb-debugging-instructions-1": "Torna al menu delle impostazioni e digita ‘debug USB’ nella barra di ricerca.",
- "activate-usb-debugging-instructions-2": "A questo punto dovresti essere nella schermata ‘Opzioni sviluppatore’. Ora tocca ‘Debug USB’ per attivarlo (su alcuni dispositivi si chiama ‘Debug Android’).",
- "bootloader-to-recovery-manually": "Bootloader a recovery",
- "bootloader-to-recovery-manually-instructions": "Ora riavvieremo il tuo dispositivo in modalità Recovery. Per favore, segui i passaggi qui sotto:",
- "bootloader-to-recovery-manually-instructions-1": "1. Nel bootloader, seleziona recovery usando Volume su e Volume giù per navigare",
- "bootloader-to-recovery-manually-instructions-2": "2. Premi Accensione per confermare",
- "bootloader-to-recovery-manually-instructions-3": "3. Se hai saltato questo passaggio, spegni il telefono e avvia in modalità Recovery premendo contemporaneamente Accensione e Volume su fino a quando il dispositivo si accende.",
- "check-update-android-version": "Controlla e aggiorna la tua versione di Android",
- "check-update-android-version-caution": "Attenzione: prima di procedere con l'installazione, verifica se è disponibile l'ultimo firmware Android per il tuo dispositivo.",
- "connect": "Connetti",
- "connect-bootloader": "Connessione del bootloader",
- "connect-bootloader-instructions-1": "Il tuo telefono ora si riavvierà in modalità bootloader
",
- "connect-bootloader-instructions-2": "Quando il telefono è acceso, connettiti in modalità bootloader
cliccando sul pulsante qui sotto",
- "connect-your-phone": "Connetti il tuo telefono",
- "connect-your-phone-instructions": "Connetti il tuo telefono al computer con un cavo USB. Rileveremo automaticamente il tuo telefono per installare /e/OS.",
- "connect-your-phone-instructions-notes": "Nota: il 'debug USB' è necessario affinché la rilevazione automatica del dispositivo funzioni. Se non l'hai ancora abilitato, ti aiuteremo nei prossimi passaggi.",
- "device-detection": "Rilevamento del dispositivo",
- "device-detection-detected": "È stato rilevato un dispositivo.",
- "device-detection-instructions-1": "Ora connetteremo il tuo telefono al browser. Quando appare questo pop-up, seleziona il tuo telefono dall'elenco.",
- "device-detection-instructions-2": "Poi apparirà una finestra pop-up sul tuo telefono. Dovrai selezionare consenti sempre da questo computer
prima di premere OK.",
- "device-detection-instructions-3": "Clicca sul pulsante qui sotto per avviare la connessione",
- "device-model-not-supported": "Modello di dispositivo non supportato",
- "device-model-not-supported-instructions": "non puoi installare /e/OS usando questo strumento",
- "device-model-not-supported-title": "Il tuo telefono {{product-name}} non è compatibile",
- "dissatisfied": "Insoddisfatto",
- "donate": "Dona",
- "enable-usb-file-transfer": "Abilita il trasferimento di file USB",
- "enable-usb-file-transfer-instructions-1": "Sempre all'interno delle 'Opzioni sviluppatore', scorri verso il basso per trovare 'Configurazione USB predefinita' e toccala.",
- "enable-usb-file-transfer-instructions-2": "Ora seleziona l'opzione 'Trasferimento di file' (su alcuni dispositivi si chiama 'modalità MTP (protocollo di trasferimento multimediale)').",
- "format-device": "Formatta il dispositivo",
- "format-device-instructions-1": "1. Seleziona Ripristino dati di fabbrica",
- "format-device-instructions-2": "2. Seleziona l'opzione Formatta dati / Ripristino dati di fabbrica",
- "format-device-instructions-3": "3. La schermata successiva mostrerà un avviso che questa azione non può essere annullata",
- "format-device-instructions-4": "4. Seleziona Formatta dati per procedere o Annulla se vuoi tornare indietro",
- "format-device-instructions-5": "5. Se hai selezionato Formatta dati, il processo di formattazione verrà completato",
- "format-device-instructions-6": "6. Lo schermo ora tornerà alla schermata di Ripristino dati di fabbrica",
- "go-to-apply-update": "Quasi fatto!",
- "go-to-apply-update-instructions-1": "1. Seleziona Applica aggiornamento",
- "go-to-apply-update-instructions-2": "2. Applica aggiornamento da adb",
- "go-to-apply-update-instructions-3": "Il dispositivo è ora in modalità sideload",
- "help": "Aiuto",
- "help-us-improve-the-tool": "Aiutaci a migliorare lo strumento",
- "help-us-improve-the-tool-instructions-1": "Per favore, valuta la tua esperienza con l'/e/OS Installer.",
- "help-us-improve-the-tool-instructions-2": "Hai qualche idea su come migliorare questo software?",
- "i-already-have-an-account": "Ho già un account",
- "i-m-ready": "Sono pronto!",
- "installation-complete": "L'installazione è completa!",
- "installation-complete-instructions-1": "Congratulazioni! Mentre il tuo telefono si avvia, dovresti vedere il logo qui sotto. Questo richiede tempo, sii paziente.",
- "installation-complete-instructions-2": "Consiglio: segui le istruzioni sul tuo telefono per configurare il tuo dispositivo. Ora puoi aggiungere di nuovo i tuoi file al telefono.",
- "let-s-get-started": "Iniziamo",
- "let-s-get-started-instruction-1": "Il processo completo di installazione richiede circa 1 ora. \nSii paziente!",
- "let-s-get-started-instruction-2": "Avrai bisogno di almeno 6GB di spazio libero sul tuo computer per\nscaricare e installare /e/OS. Assicurati di avere abbastanza spazio libero sul disco.",
- "let-s-get-started-instruction-3": "Prima di installare /e/OS, assicurati che il tuo telefono abbia almeno il 50% di batteria",
- "let-s-get-started-instruction-4": "Tutti i dati verranno cancellati dal tuo smartphone durante l'installazione\nquindi ti consigliamo di eseguire il backup dei tuoi dati.",
- "let-s-get-started-instruction-5": "È necessario un cavo dati USB funzionante. I cavi di alimentazione non trasferiscono dati\ne non funzioneranno! Raccomandiamo USB 3.x o successivi.",
- "let-s-get-started-instruction-title-1": "1. Libera un po' di tempo",
- "let-s-get-started-instruction-title-2": "2. Libera spazio sul disco",
- "let-s-get-started-instruction-title-3": "3. Carica il tuo telefono",
- "let-s-get-started-instruction-title-4": "4. Esegui il backup dei tuoi dati",
- "let-s-get-started-instruction-title-5": "5. Prendi un cavo dati USB",
- "locking": "Blocco",
- "locking-instructions-1": "Il tuo telefono chiede uno sblocco. Seleziona lock bootloader
",
- "locking-instructions-2": "Se il dispositivo non si riavvia automaticamente, riavvialo",
- "murena-workspace-account": "Account Murena Workspace",
- "murena-workspace-account-instructions": "Mantieni i tuoi dati al sicuro e sincronizza questo dispositivo con il tuo account personale Murena Workspace. 1GB gratuito e piani a pagamento disponibili per più spazio di archiviazione.",
- "navigator-detection": "Rilevamento del browser",
- "navigator-not-supported": "Il tuo browser non è supportato",
- "navigator-not-supported-instructions": "Puoi usare i seguenti browser",
- "neutral": "Neutro",
- "next": "Successivo",
- "ready-to-install-e-os": "Ora sei pronto per installare /e/OS.",
- "recovery-to-bootloader": "Recovery
a Bootloader
",
- "recovery-to-bootloader-instructions": "Seleziona Avanzato",
- "recovery-to-bootloader-instructions-1": "1. Seleziona Advanced
",
- "recovery-to-bootloader-instructions-2": "2. Seleziona Reboot to bootloader
",
- "satisfied": "Soddisfatto",
- "send-to-e-team": "Invia al team di /e/",
- "sideload": "Installazione in corso",
- "sideload-instructions-1": "Lo schermo mostrerà la percentuale di completamento... ",
- "sideload-instructions-2": "Questo potrebbe fermarsi al 47%, dagli tempo.",
- "sideload-instructions-3": "Una volta che l'installazione è terminata, il telefono tornerà alla schermata principale.",
- "sideload-instructions-4": "Solo allora puoi cliccare su Next
.",
- "sign-up-free": "Iscriviti GRATIS",
- "skip": "Salta",
- "start": "Inizia",
- "this-might-take-some-time-please-be-patient": "Questo potrebbe richiedere del tempo, per favore sii paziente",
- "unlocking-instructions-1": "Il tuo telefono chiede uno sblocco. Seleziona unlock bootloader
",
- "unlocking-instructions-2": "Se il dispositivo non si riavvia automaticamente, riavvialo. Ora dovrebbe essere sbloccato.",
- "unlocking-instructions-3": "Poiché il dispositivo si resetta completamente, dovrai riattivare il debug USB.",
- "unlocking-instructions-4": "Supera la configurazione e fai clic su successivo",
- "very-dissatisfied": "Molto insoddisfatto",
- "very-satisfied": "Molto soddisfatto"
+ "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Es 1: prima di installare /e/OS Android 12, dovresti aggiornare all'ultima versione di stock di Android 12",
+ "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Es 2: o se stai installando /e/OS Android 11, assicurati di aggiornare all'ultima versione di stock di Android 11",
+ "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Es 3: allo stesso modo, se stai installando /e/OS Android 11, dovrebbe essere l'ultima versione di stock di Android 10",
+ "activate-developer-options": "Attiva le opzioni sviluppatore",
+ "activate-developer-options-instructions-1": "1. Apri il menu delle impostazioni e digita ‘build’ nella barra di ricerca.",
+ "activate-developer-options-instructions-2": "2. Nella schermata successiva, trova ‘Numero di build’ e tocca 7 volte su di esso.",
+ "activate-usb-debugging": "Attiva il debug USB",
+ "activate-usb-debugging-instructions-1": "Torna al menu delle impostazioni e digita ‘debug USB’ nella barra di ricerca.",
+ "activate-usb-debugging-instructions-2": "A questo punto dovresti essere nella schermata ‘Opzioni sviluppatore’. Ora tocca ‘Debug USB’ per attivarlo (su alcuni dispositivi si chiama ‘Debug Android’).",
+ "bootloader-to-recovery-manually": "Bootloader a recovery",
+ "bootloader-to-recovery-manually-instructions": "Ora riavvieremo il tuo dispositivo in modalità Recovery. Per favore, segui i passaggi qui sotto:",
+ "bootloader-to-recovery-manually-instructions-1": "1. Nel bootloader, seleziona recovery usando Volume su e Volume giù per navigare",
+ "bootloader-to-recovery-manually-instructions-2": "2. Premi Accensione per confermare",
+ "bootloader-to-recovery-manually-instructions-3": "3. Se hai saltato questo passaggio, spegni il telefono e avvia in modalità Recovery premendo contemporaneamente Accensione e Volume su fino a quando il dispositivo si accende.",
+ "check-update-android-version": "Controlla e aggiorna la tua versione di Android",
+ "check-update-android-version-caution": "Attenzione: prima di procedere con l'installazione, verifica se è disponibile l'ultimo firmware Android per il tuo dispositivo.",
+ "connect": "Connetti",
+ "connect-bootloader": "Connessione del bootloader",
+ "connect-bootloader-instructions-1": "Il tuo telefono ora si riavvierà in modalità bootloader
",
+ "connect-bootloader-instructions-2": "Quando il telefono è acceso, connettiti in modalità bootloader
cliccando sul pulsante qui sotto",
+ "connect-your-phone": "Connetti il tuo telefono",
+ "connect-your-phone-instructions": "Connetti il tuo telefono al computer con un cavo USB. Rileveremo automaticamente il tuo telefono per installare /e/OS.",
+ "connect-your-phone-instructions-notes": "Nota: il 'debug USB' è necessario affinché la rilevazione automatica del dispositivo funzioni. Se non l'hai ancora abilitato, ti aiuteremo nei prossimi passaggi.",
+ "device-detection": "Rilevamento del dispositivo",
+ "device-detection-detected": "È stato rilevato un dispositivo.",
+ "device-detection-instructions-1": "Ora connetteremo il tuo telefono al browser. Quando appare questo pop-up, seleziona il tuo telefono dall'elenco.",
+ "device-detection-instructions-2": "Poi apparirà una finestra pop-up sul tuo telefono. Dovrai selezionare consenti sempre da questo computer
prima di premere OK.",
+ "device-detection-instructions-3": "Clicca sul pulsante qui sotto per avviare la connessione",
+ "device-model-not-supported": "Modello di dispositivo non supportato",
+ "device-model-not-supported-instructions": "non puoi installare /e/OS usando questo strumento",
+ "device-model-not-supported-title": "Il tuo telefono {{product-name}} non è compatibile",
+ "dissatisfied": "Insoddisfatto",
+ "donate": "Dona",
+ "enable-usb-file-transfer": "Abilita il trasferimento di file USB",
+ "enable-usb-file-transfer-instructions-1": "Sempre all'interno delle 'Opzioni sviluppatore', scorri verso il basso per trovare 'Configurazione USB predefinita' e toccala.",
+ "enable-usb-file-transfer-instructions-2": "Ora seleziona l'opzione 'Trasferimento di file' (su alcuni dispositivi si chiama 'modalità MTP (protocollo di trasferimento multimediale)').",
+ "format-device": "Formatta il dispositivo",
+ "format-device-instructions-1": "1. Seleziona Ripristino dati di fabbrica",
+ "format-device-instructions-2": "2. Seleziona l'opzione Formatta dati / Ripristino dati di fabbrica",
+ "format-device-instructions-3": "3. La schermata successiva mostrerà un avviso che questa azione non può essere annullata",
+ "format-device-instructions-4": "4. Seleziona Formatta dati per procedere o Annulla se vuoi tornare indietro",
+ "format-device-instructions-5": "5. Se hai selezionato Formatta dati, il processo di formattazione verrà completato",
+ "format-device-instructions-6": "6. Lo schermo ora tornerà alla schermata di Ripristino dati di fabbrica",
+ "go-to-apply-update": "Quasi fatto!",
+ "go-to-apply-update-instructions-1": "1. Seleziona Applica aggiornamento",
+ "go-to-apply-update-instructions-2": "2. Applica aggiornamento da adb",
+ "go-to-apply-update-instructions-3": "Il dispositivo è ora in modalità sideload",
+ "help": "Aiuto",
+ "help-us-improve-the-tool": "Aiutaci a migliorare lo strumento",
+ "help-us-improve-the-tool-instructions-1": "Per favore, valuta la tua esperienza con l'/e/OS Installer.",
+ "help-us-improve-the-tool-instructions-2": "Hai qualche idea su come migliorare questo software?",
+ "i-already-have-an-account": "Ho già un account",
+ "i-m-ready": "Sono pronto!",
+ "installation-complete": "L'installazione è completa!",
+ "installation-complete-instructions-1": "Congratulazioni! Mentre il tuo telefono si avvia, dovresti vedere il logo qui sotto. Questo richiede tempo, sii paziente.",
+ "installation-complete-instructions-2": "Consiglio: segui le istruzioni sul tuo telefono per configurare il tuo dispositivo. Ora puoi aggiungere di nuovo i tuoi file al telefono.",
+ "let-s-get-started": "Iniziamo",
+ "let-s-get-started-instruction-1": "Il processo completo di installazione richiede circa 1 ora. \nSii paziente!",
+ "let-s-get-started-instruction-2": "Avrai bisogno di almeno 6GB di spazio libero sul tuo computer per\nscaricare e installare /e/OS. Assicurati di avere abbastanza spazio libero sul disco.",
+ "let-s-get-started-instruction-3": "Prima di installare /e/OS, assicurati che il tuo telefono abbia almeno il 50% di batteria",
+ "let-s-get-started-instruction-4": "Tutti i dati verranno cancellati dal tuo smartphone durante l'installazione\nquindi ti consigliamo di eseguire il backup dei tuoi dati.",
+ "let-s-get-started-instruction-5": "È necessario un cavo dati USB funzionante. I cavi di alimentazione non trasferiscono dati\ne non funzioneranno! Raccomandiamo USB 3.x o successivi.",
+ "let-s-get-started-instruction-title-1": "1. Libera un po' di tempo",
+ "let-s-get-started-instruction-title-2": "2. Libera spazio sul disco",
+ "let-s-get-started-instruction-title-3": "3. Carica il tuo telefono",
+ "let-s-get-started-instruction-title-4": "4. Esegui il backup dei tuoi dati",
+ "let-s-get-started-instruction-title-5": "5. Prendi un cavo dati USB",
+ "locking": "Blocco",
+ "locking-instructions-1": "Il tuo telefono chiede uno sblocco. Seleziona lock bootloader
",
+ "locking-instructions-2": "Se il dispositivo non si riavvia automaticamente, riavvialo",
+ "murena-workspace-account": "Account Murena Workspace",
+ "murena-workspace-account-instructions": "Mantieni i tuoi dati al sicuro e sincronizza questo dispositivo con il tuo account personale Murena Workspace. 1GB gratuito e piani a pagamento disponibili per più spazio di archiviazione.",
+ "navigator-detection": "Rilevamento del browser",
+ "navigator-not-supported": "Il tuo browser non è supportato",
+ "navigator-not-supported-instructions": "Puoi usare i seguenti browser",
+ "neutral": "Neutro",
+ "next": "Successivo",
+ "ready-to-install-e-os": "Ora sei pronto per installare /e/OS.",
+ "recovery-to-bootloader": "Recovery
a Bootloader
",
+ "recovery-to-bootloader-instructions": "Seleziona Avanzato",
+ "recovery-to-bootloader-instructions-1": "1. Seleziona Advanced
",
+ "recovery-to-bootloader-instructions-2": "2. Seleziona Reboot to bootloader
",
+ "satisfied": "Soddisfatto",
+ "send-to-e-team": "Invia al team di /e/",
+ "sideload": "Installazione in corso",
+ "sideload-instructions-1": "Lo schermo mostrerà la percentuale di completamento... ",
+ "sideload-instructions-2": "Questo potrebbe fermarsi al 47%, dagli tempo.",
+ "sideload-instructions-3": "Una volta che l'installazione è terminata, il telefono tornerà alla schermata principale.",
+ "sideload-instructions-4": "Solo allora puoi cliccare su Next
.",
+ "sign-up-free": "Iscriviti GRATIS",
+ "skip": "Salta",
+ "start": "Inizia",
+ "this-might-take-some-time-please-be-patient": "Questo potrebbe richiedere del tempo, per favore sii paziente",
+ "unlocking-instructions-1": "Il tuo telefono chiede uno sblocco. Seleziona unlock bootloader
",
+ "unlocking-instructions-2": "Se il dispositivo non si riavvia automaticamente, riavvialo. Ora dovrebbe essere sbloccato.",
+ "unlocking-instructions-3": "Poiché il dispositivo si resetta completamente, dovrai riattivare il debug USB.",
+ "unlocking-instructions-4": "Supera la configurazione e fai clic su successivo",
+ "very-dissatisfied": "Molto insoddisfatto",
+ "very-satisfied": "Molto soddisfatto"
}
diff --git a/app/public/assets/languages/nb-NO.json b/app/public/assets/languages/nb-NO.json
index 478d64be615b6febd89b4a52771fc05e0a8ee6df..fa415a308ca6680a9fb1c7f2964157025fa3a893 100644
--- a/app/public/assets/languages/nb-NO.json
+++ b/app/public/assets/languages/nb-NO.json
@@ -1,44 +1,44 @@
{
- "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Eks. 1: før du installerer /e/OS Android 12, bør du oppdatere til den nyeste Android 12",
- "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Eks. 2: eller hvis du installerer /e/OS Android 11, må du sørge for å oppdatere til den nyeste Android 11",
- "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Eks. 3: likeså, hvis du installerer /e/OS Android 11, bør det være den nyeste Android 10",
- "activate-developer-options": "Aktiver utvikleralternativer",
- "activate-usb-debugging": "Aktiver USB-feilsøking",
- "activate-developer-options-instructions-1": "1. Åpne menyen Innstillinger, og skriv \"bygg\" i søkefeltet.",
- "activate-developer-options-instructions-2": "2. På neste skjermbilde finner du \"Byggnummer\" og trykker 7 ganger på det.",
- "activate-usb-debugging-instructions-1": "Gå tilbake til menyen Innstillinger og skriv \"USB-feilsøking\" i søkefeltet.",
- "activate-usb-debugging-instructions-2": "På dette tidspunktet bør du være i skjermbildet \"Utvikleralternativer\". Trykk nå på \"USB-feilsøking\" for å aktivere den (på noen enheter kalles den \"Android-feilsøking\").",
- "check-update-android-version-caution": "Advarsel: Før du fortsetter med installasjonen, må du kontrollere at den nyeste Android-versjonen er tilgjengelig for enheten din.",
- "enable-usb-file-transfer-instructions-1": "Fortsatt inne i \"Utvikleralternativer\", bla nedover for å finne \"Standard USB-konfigurasjon\" og trykk på den.",
- "connect-bootloader-instructions-2": "Når telefonen er på, kan du aktivere bootloader
-modus ved å klikke på knappen nedenfor",
- "connect-your-phone-instructions-notes": "Husk: \"USB-feilsøking\" må være aktivert for at automatisk enhetsgjenkjenning skal fungere. Hvis du ikke har aktivert det ennå, vil vi hjelpe deg i de neste trinnene.",
- "format-device-instructions-3": "3. Neste skjermbilde viser en advarsel om at denne handlingen ikke kan angres",
- "bootloader-to-recovery-manually": "Bootloader til gjenoppretting",
- "bootloader-to-recovery-manually-instructions": "Nå starter vi enheten på nytt i gjenopprettingsmodus. Vennligst følg trinnene nedenfor:",
- "bootloader-to-recovery-manually-instructions-1": "1. I bootloader, velger du gjenoppretting ved å bruke Volum opp og Volum ned for å navigere",
- "bootloader-to-recovery-manually-instructions-3": "3. Hvis du gikk glipp av dette trinnet, kan du slå av enheten og starte den på nytt i gjenopprettingsmodus ved å trykke på og holde inne Av/På-knappen og Volum opp samtidig, til enheten slås på.",
- "bootloader-to-recovery-manually-instructions-2": "2. Trykk på Av/På-knappen for å bekrefte",
- "check-update-android-version": "Sjekk og oppdater Android-versjonen",
- "connect": "Koble til",
- "connect-bootloader": "Bootloader-tilkobling",
- "connect-bootloader-instructions-1": "Telefonen vil nå starte på nytt i bootloader
-modus",
- "connect-your-phone": "Koble til telefonen din",
- "connect-your-phone-instructions": "Koble telefonen til datamaskinen med en USB-kabel. Vi vil automatisk oppdage telefonen din for å installere /e/OS.",
- "device-detection": "Enhetsgjenkjenning",
- "device-detection-detected": "En enhet har blitt oppdaget.",
- "device-detection-instructions-1": "Vi kobler nå telefonen din til nettleseren. Når dette popup-vinduet vises, velger du telefonen din fra listen.",
- "device-detection-instructions-2": "Et popup-vindu vises deretter på telefonen din. Du må krysse av for Tillat alltid fra denne datamaskinen
før du trykker Ok.",
- "device-detection-instructions-3": "Klikk på knappen nedenfor for å koble til",
- "device-model-not-supported": "Enhetsmodellen støttes ikke",
- "device-model-not-supported-instructions": "du kan ikke installere /e/OS ved hjelp av dette programmet",
- "device-model-not-supported-title": "Telefonen din {{product-name}} er ikke kompatibel",
- "dissatisfied": "Misfornøyd",
- "donate": "Doner",
- "enable-usb-file-transfer": "Aktiver USB-filoverføring",
- "enable-usb-file-transfer-instructions-2": "Velg alternativet \"Filoverføring\" (på noen enheter kalles det \"MTP-modus (media transfer protocol)\").",
- "format-device": "Formater enheten",
- "format-device-instructions-1": "1. Velg Fabrikkinnstillinger",
- "format-device-instructions-2": "2. Velg alternativet Formater data / Tilbakestill til fabrikkinnstillinger",
- "format-device-instructions-4": "4. Velg Formater data for å fortsette eller Avbryt hvis du vil gå tilbake",
- "format-device-instructions-5": "5. Hvis du har valgt Formater data, fullføres formateringsprosessen"
+ "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Eks. 1: før du installerer /e/OS Android 12, bør du oppdatere til den nyeste Android 12",
+ "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Eks. 2: eller hvis du installerer /e/OS Android 11, må du sørge for å oppdatere til den nyeste Android 11",
+ "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Eks. 3: likeså, hvis du installerer /e/OS Android 11, bør det være den nyeste Android 10",
+ "activate-developer-options": "Aktiver utvikleralternativer",
+ "activate-usb-debugging": "Aktiver USB-feilsøking",
+ "activate-developer-options-instructions-1": "1. Åpne menyen Innstillinger, og skriv \"bygg\" i søkefeltet.",
+ "activate-developer-options-instructions-2": "2. På neste skjermbilde finner du \"Byggnummer\" og trykker 7 ganger på det.",
+ "activate-usb-debugging-instructions-1": "Gå tilbake til menyen Innstillinger og skriv \"USB-feilsøking\" i søkefeltet.",
+ "activate-usb-debugging-instructions-2": "På dette tidspunktet bør du være i skjermbildet \"Utvikleralternativer\". Trykk nå på \"USB-feilsøking\" for å aktivere den (på noen enheter kalles den \"Android-feilsøking\").",
+ "check-update-android-version-caution": "Advarsel: Før du fortsetter med installasjonen, må du kontrollere at den nyeste Android-versjonen er tilgjengelig for enheten din.",
+ "enable-usb-file-transfer-instructions-1": "Fortsatt inne i \"Utvikleralternativer\", bla nedover for å finne \"Standard USB-konfigurasjon\" og trykk på den.",
+ "connect-bootloader-instructions-2": "Når telefonen er på, kan du aktivere bootloader
-modus ved å klikke på knappen nedenfor",
+ "connect-your-phone-instructions-notes": "Husk: \"USB-feilsøking\" må være aktivert for at automatisk enhetsgjenkjenning skal fungere. Hvis du ikke har aktivert det ennå, vil vi hjelpe deg i de neste trinnene.",
+ "format-device-instructions-3": "3. Neste skjermbilde viser en advarsel om at denne handlingen ikke kan angres",
+ "bootloader-to-recovery-manually": "Bootloader til gjenoppretting",
+ "bootloader-to-recovery-manually-instructions": "Nå starter vi enheten på nytt i gjenopprettingsmodus. Vennligst følg trinnene nedenfor:",
+ "bootloader-to-recovery-manually-instructions-1": "1. I bootloader, velger du gjenoppretting ved å bruke Volum opp og Volum ned for å navigere",
+ "bootloader-to-recovery-manually-instructions-3": "3. Hvis du gikk glipp av dette trinnet, kan du slå av enheten og starte den på nytt i gjenopprettingsmodus ved å trykke på og holde inne Av/På-knappen og Volum opp samtidig, til enheten slås på.",
+ "bootloader-to-recovery-manually-instructions-2": "2. Trykk på Av/På-knappen for å bekrefte",
+ "check-update-android-version": "Sjekk og oppdater Android-versjonen",
+ "connect": "Koble til",
+ "connect-bootloader": "Bootloader-tilkobling",
+ "connect-bootloader-instructions-1": "Telefonen vil nå starte på nytt i bootloader
-modus",
+ "connect-your-phone": "Koble til telefonen din",
+ "connect-your-phone-instructions": "Koble telefonen til datamaskinen med en USB-kabel. Vi vil automatisk oppdage telefonen din for å installere /e/OS.",
+ "device-detection": "Enhetsgjenkjenning",
+ "device-detection-detected": "En enhet har blitt oppdaget.",
+ "device-detection-instructions-1": "Vi kobler nå telefonen din til nettleseren. Når dette popup-vinduet vises, velger du telefonen din fra listen.",
+ "device-detection-instructions-2": "Et popup-vindu vises deretter på telefonen din. Du må krysse av for Tillat alltid fra denne datamaskinen
før du trykker Ok.",
+ "device-detection-instructions-3": "Klikk på knappen nedenfor for å koble til",
+ "device-model-not-supported": "Enhetsmodellen støttes ikke",
+ "device-model-not-supported-instructions": "du kan ikke installere /e/OS ved hjelp av dette programmet",
+ "device-model-not-supported-title": "Telefonen din {{product-name}} er ikke kompatibel",
+ "dissatisfied": "Misfornøyd",
+ "donate": "Doner",
+ "enable-usb-file-transfer": "Aktiver USB-filoverføring",
+ "enable-usb-file-transfer-instructions-2": "Velg alternativet \"Filoverføring\" (på noen enheter kalles det \"MTP-modus (media transfer protocol)\").",
+ "format-device": "Formater enheten",
+ "format-device-instructions-1": "1. Velg Fabrikkinnstillinger",
+ "format-device-instructions-2": "2. Velg alternativet Formater data / Tilbakestill til fabrikkinnstillinger",
+ "format-device-instructions-4": "4. Velg Formater data for å fortsette eller Avbryt hvis du vil gå tilbake",
+ "format-device-instructions-5": "5. Hvis du har valgt Formater data, fullføres formateringsprosessen"
}
diff --git a/app/public/assets/languages/ru.json b/app/public/assets/languages/ru.json
index 2d1a4379d797ddef0309c0517ae9305d29b82368..325927c563062495a0dacec460e179682728232f 100644
--- a/app/public/assets/languages/ru.json
+++ b/app/public/assets/languages/ru.json
@@ -1,14 +1,14 @@
{
- "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Вывод 1: перед установкой /e/OS Android 12 необходимо обновить до последней стоковой версии Android 12",
- "activate-developer-options-instructions-1": "1. Откройте меню настроек и введите \"build\" в строке поиска.",
- "activate-usb-debugging-instructions-2": "2. В этот момент вы должны оказаться на экране \"Параметры разработчика\". Теперь нажмите на \"Отладка USB\", чтобы активировать ее (на некоторых устройствах она называется \"Отладка Android\").",
- "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Вывод 3: Аналогично, если вы устанавливаете /e/OS Android 11, это должна быть последняя стоковая версия Android 10",
- "activate-developer-options": "Активируйте Опции разработчика",
- "activate-developer-options-instructions-2": "2. На следующем экране найдите \"Build number\" и нажмите на него 7 раз.",
- "activate-usb-debugging": "Активируйте отладку по USB",
- "activate-usb-debugging-instructions-1": "1. Вернитесь в меню настроек и введите в строке поиска \"Отладка USB\".",
- "android-version-not-supported": "Устаревшая версия Android",
- "android-version-not-supported-instructions": "Обновите свою систему до минимально необходимой версии {{android-version-required}}
",
- "android-version-not-supported-title": "Ваша версия Android {{android-version}}
не поддерживается",
- "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Вывод 2: или если вы устанавливаете /e/OS Android 11, обязательно обновитесь до последней стоковой версии Android 11"
+ "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Вывод 1: перед установкой /e/OS Android 12 необходимо обновить до последней стоковой версии Android 12",
+ "activate-developer-options-instructions-1": "1. Откройте меню настроек и введите \"build\" в строке поиска.",
+ "activate-usb-debugging-instructions-2": "2. В этот момент вы должны оказаться на экране \"Параметры разработчика\". Теперь нажмите на \"Отладка USB\", чтобы активировать ее (на некоторых устройствах она называется \"Отладка Android\").",
+ "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Вывод 3: Аналогично, если вы устанавливаете /e/OS Android 11, это должна быть последняя стоковая версия Android 10",
+ "activate-developer-options": "Активируйте Опции разработчика",
+ "activate-developer-options-instructions-2": "2. На следующем экране найдите \"Build number\" и нажмите на него 7 раз.",
+ "activate-usb-debugging": "Активируйте отладку по USB",
+ "activate-usb-debugging-instructions-1": "1. Вернитесь в меню настроек и введите в строке поиска \"Отладка USB\".",
+ "android-version-not-supported": "Устаревшая версия Android",
+ "android-version-not-supported-instructions": "Обновите свою систему до минимально необходимой версии {{android-version-required}}
",
+ "android-version-not-supported-title": "Ваша версия Android {{android-version}}
не поддерживается",
+ "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Вывод 2: или если вы устанавливаете /e/OS Android 11, обязательно обновитесь до последней стоковой версии Android 11"
}
diff --git a/app/public/assets/languages/sv.json b/app/public/assets/languages/sv.json
index fc2805ef63cbbd0059878ba6c40241bf3302f626..4c33d7d583030cb582f9b3e35164eedfe577c0b4 100644
--- a/app/public/assets/languages/sv.json
+++ b/app/public/assets/languages/sv.json
@@ -1,110 +1,110 @@
{
- "donate": "Donera",
- "connect": "Anslut",
- "connect-your-phone": "Anslut din telefon",
- "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Exempel 1: innan installation av /e/OS Android 12 bör du uppgradera till den senaste standardversionen av Android 12",
- "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Exempel 2: eller om du installerar /e/OS Android 11, se till att uppgradera till den senaste standardversionen av Android 11",
- "next": "Nästa",
- "connect-bootloader": "Anslutning starthanteraren",
- "connect-bootloader-instructions-2": "När din telefon är på ansluter du telefonen i läget starthanteraren
genom att klicka på knappen nedan",
- "connect-your-phone-instructions-notes": "Obs! \"USB-felsökning\" krävs för att automatisk enhetsupptäckt ska fungera. Om du inte har aktiverat det än kommer vi hjälpa dig i de kommande stegen.",
- "device-detection": "Enhetsupptäckt",
- "device-detection-detected": "En enhet har upptäckts.",
- "device-detection-instructions-1": "Vi kommer nu ansluta din telefon till webbläsaren. När du ser en popupp väljer du din telefon från listan.",
- "device-detection-instructions-3": "Klicka på knappen nedan för att starta anslutningen",
- "device-model-not-supported": "Enhetens modell stöds inte",
- "device-model-not-supported-instructions": "du kan inte installera /e/OS med detta program",
- "device-model-not-supported-title": "Din telefon {{product-name}} är inte kompatibel",
- "dissatisfied": "Inte nöjd",
- "enable-usb-file-transfer": "Aktivera filöverföring via USB",
- "connect-bootloader-instructions-1": "Din telefon kommer nu att starta om i läget starthanteraren
",
- "connect-your-phone-instructions": "Anslut din telefon till din dator med en USB-kabel. Vi kommer automatiskt upptäcka din telefon för att installera /e/OS.",
- "device-detection-instructions-2": "Ett popupp-fönster kommer synas på din telefon. Du behöver markera tillåt alltid från denna dator
innan du trycker ok.",
- "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Exempel 3: och om du installerar /e/OS Android 11 bör det vara den senaste standardversionen av Android 10",
- "activate-developer-options": "Aktivera utvecklaralternativ",
- "activate-developer-options-instructions-1": "1. Öppna inställningsmenyn och skriv \"build\" i sökfältet.",
- "activate-developer-options-instructions-2": "2. På nästa skärm letar du upp \"Build number\" och trycker 7 gånger på det.",
- "activate-usb-debugging": "Aktivera USB-felsökning",
- "activate-usb-debugging-instructions-2": "2. Nu bör du vara i \"Utvecklaralternativ\". Tryck nu på \"USB-felsökning\" för att aktivera det (på vissa enheter kan det kallas (Android-felsökning\").",
- "activate-usb-debugging-instructions-1": "1. Gå tillbaka till inställningsmenyn och skriv \"USB-felsökning\" i sökfältet.",
- "bootloader-to-recovery-manually": "Starthanterare till återställning",
- "bootloader-to-recovery-manually-instructions": "Nu ska vi starta om din enhet i Återställningsläget. Följ nedan steg:",
- "bootloader-to-recovery-manually-instructions-1": "1. Välj Återställningsläge
i starthanteraren genom att navigera med Volum upp och Volym ned",
- "bootloader-to-recovery-manually-instructions-2": "2. Tryck på Av/På-knappen för att bekräfta",
- "check-update-android-version": "Kontrollera och uppdatera din Androidversion",
- "check-update-android-version-caution": "Varning: innan du fortsätter med installationen, kontrollera om den senaste Androidversionen finns tillgänglig för din enhet.",
- "enable-usb-file-transfer-instructions-1": "Medan du fortfarande är inne i \"Utvecklaralternativ\" skrollar du ner för att hitta \"USB standardkonfiguration\" och trycker på det.",
- "format-device": "Formatera enheten",
- "format-device-instructions-1": "1. Välj fabriksåterställning
",
- "format-device-instructions-2": "2. Välj alternativet Formatera data/Fabriksåterställning
",
- "format-device-instructions-3": "3. Nästa skärm kommer visa en varning om att denna åtgärd inte kan göras ogjord",
- "format-device-instructions-4": "4. Välj Formatera data
för att fortsätta",
- "format-device-instructions-5": "5. Vänta medan formateringsprocessen slutförs",
- "format-device-instructions-6": "6. Skärmen kommer nu gå tillbaka till skärmen Fabriksåterställning",
- "help": "Hjälp",
- "help-us-improve-the-tool": "Hjälp oss förbättra verktyget",
- "help-us-improve-the-tool-instructions-1": "Vänligen betygsätt upplevelsen med /e/OS Installer.",
- "help-us-improve-the-tool-instructions-2": "Har du några tankar om hur programvaran skulle kunna förbättras?",
- "i-already-have-an-account": "Jag har redan ett konto",
- "i-m-ready": "Jag är redo!",
- "installation-complete": "Installationen är klar!",
- "installation-complete-instructions-1": "Grattis! Medan din telefon startar bör du se loggan nedan. Detta tar tid, vänligen var tålmodig.",
- "go-to-apply-update": "Nästan där!",
- "go-to-apply-update-instructions-1": "1. Välj applicera uppdatering
.",
- "go-to-apply-update-instructions-2": "2. Sedan Applicera uppdatering från adb
.",
- "installation-complete-instructions-2": "Tips: följ instruktionerna på din telefon för att ställa in din enhet. Du kan nu föra över dina filer tillbaka till din telefon.",
- "let-s-get-started-instruction-1": "Hela installationsprocessen kräver cirka 1 timme. Var\n tålmodig!",
- "enable-usb-file-transfer-instructions-2": "Välj nu alternativet Filöverföring (på en del enheter kallas det \"MTP-läge (media transfer protocol)\").",
- "format-device-instructions-7": "7. Tryck på bakåt
pilen och tryck på Nästa
",
- "locking-instructions-3": "Klicka sedan på nästa",
- "murena-workspace-account": "Murena Workspace-konto",
- "murena-workspace-account-instructions": "Håll din data säker och synkronisera denna enheten med ditt personliga Murena Workspace-konto. 1 GB gratis och det finns betalplaner för mer utrymme.",
- "navigator-detection": "Navigatorupptäckt",
- "navigator-not-supported": "Din navigator stöds inte",
- "navigator-not-supported-instructions": "Du kan använda följande webbläsare",
- "neutral": "Neutral",
- "unlocking-instructions-1-a": "Använd Av/På-knappen för att bekräfta.",
- "android-version-not-supported": "Androidversionen är utdaterad",
- "android-version-not-supported-title": "Din Androidverson {{android-version}}
stöds inte",
- "android-version-not-supported-instructions": "Uppdatera ditt system till den version som är minimikravet {{android-version-required}}
",
- "go-to-apply-update-instructions-3": "3. Enheten är nu i \"sideload\"-läge, du är nu redo för nästa steg.",
- "let-s-get-started": "Nu sätter vi igång",
- "let-s-get-started-instruction-2": "Du behöver minst 6 GB ledigt utrymme på din dator\n för att hämta och installera /e/OS. Se till att du har tillräckligt med ledigt utrymme på hårddisken.",
- "let-s-get-started-instruction-3": "Se till att telefonens batteri har minst 50% laddning kvar innan du installerar /e/OS",
- "let-s-get-started-instruction-4": "All data kommer raderas från din smarta telefon under installationen,\n vi rekommenderar att du tar en säkerhetskopia av din data.",
- "let-s-get-started-instruction-5": "Det krävs en fungerande USB-datakabel. Laddkablar överför inte data\n och kommer inte att fungera! Vi rekommenderar USB 3.x eller senare.",
- "let-s-get-started-instruction-title-1": "1. Frigör lite tid",
- "let-s-get-started-instruction-title-2": "2. Frigör lagringsutrymme",
- "let-s-get-started-instruction-title-3": "3. Ladda din telefon",
- "let-s-get-started-instruction-title-4": "4. Säkerhetskopiera din data",
- "let-s-get-started-instruction-title-5": "5. Ta en USB-datakabel",
- "locking": "Låser",
- "locking-instructions-1": "Din telefon frågar om att låsas upp. Välj lås starthanteraren
",
- "locking-instructions-2": "Starta om din telefon om den inte startar om automatiskt",
- "ready-to-install-e-os": "Du är nu redo att installera /e/OS.",
- "recovery-to-bootloader": "Återställning till Starthanteraren",
- "recovery-to-bootloader-instructions": "I huvudmenyn",
- "recovery-to-bootloader-instructions-1": "1. Välj Avancerad
",
- "recovery-to-bootloader-instructions-2": "2. Välj Starta om till starthanteraren
",
- "satisfied": "Nöjd",
- "send-to-e-team": "Skicka till Murena-teamet",
- "sideload": "Installation pågår",
- "sideload-instructions-1": "Skärmen kommer visa processen ... ",
- "sideload-instructions-2": "Detta kan ta flera minuter, ge det lite tid.",
- "sideload-instructions-3": "När installationen är klar kommer telefonen att gå tillbaka till huvudskärmen.",
- "sideload-instructions-4": "Endast då kan du klicka på Nästa
.",
- "skip": "Hoppa över",
- "start": "Starta",
- "this-might-take-some-time-please-be-patient": "Detta kan ta lite tid, vänligen ha tålamod",
- "unlocking-instructions-1": "Din telefon frågaor om upplåsning. Välj lås upp starthanteraren
genom att navigera med Volym upp och Volym ned.",
- "unlocking-instructions-2": "Starta om enheten om den inte startar om automatiskt.",
- "bootloader-to-recovery-manually-instructions-3": "3. Vänta på att telefonen startar i återställning",
- "go-to-apply-update-instructions-4": "Observera! Inför nästa steg kanske webbläsaren behöver återansluta till din telefon. Om ett popup-fönster dyker upp, välj din telefon från listan.",
- "installing": "Installerar",
- "unlocking-instructions-2-a": "Din enhet kommer starta om. Vänta till Starthanterarens skärm visas igen innan du går vidare till nästa steg",
- "very-satisfied": "Mycket nöjd",
- "unlocking-instructions-3": "Eftersom enheter helt återställs kommer du behöva aktivera USB-felsökning igen.",
- "unlocking-instructions-4": "Hoppa över inställningen på telefonen och klicka på nästa",
- "very-dissatisfied": "Mycket missnöjd",
- "sign-up-free": "Registrera dig GRATIS"
+ "donate": "Donera",
+ "connect": "Anslut",
+ "connect-your-phone": "Anslut din telefon",
+ "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Exempel 1: innan installation av /e/OS Android 12 bör du uppgradera till den senaste standardversionen av Android 12",
+ "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Exempel 2: eller om du installerar /e/OS Android 11, se till att uppgradera till den senaste standardversionen av Android 11",
+ "next": "Nästa",
+ "connect-bootloader": "Anslutning starthanteraren",
+ "connect-bootloader-instructions-2": "När din telefon är på ansluter du telefonen i läget starthanteraren
genom att klicka på knappen nedan",
+ "connect-your-phone-instructions-notes": "Obs! \"USB-felsökning\" krävs för att automatisk enhetsupptäckt ska fungera. Om du inte har aktiverat det än kommer vi hjälpa dig i de kommande stegen.",
+ "device-detection": "Enhetsupptäckt",
+ "device-detection-detected": "En enhet har upptäckts.",
+ "device-detection-instructions-1": "Vi kommer nu ansluta din telefon till webbläsaren. När du ser en popupp väljer du din telefon från listan.",
+ "device-detection-instructions-3": "Klicka på knappen nedan för att starta anslutningen",
+ "device-model-not-supported": "Enhetens modell stöds inte",
+ "device-model-not-supported-instructions": "du kan inte installera /e/OS med detta program",
+ "device-model-not-supported-title": "Din telefon {{product-name}} är inte kompatibel",
+ "dissatisfied": "Inte nöjd",
+ "enable-usb-file-transfer": "Aktivera filöverföring via USB",
+ "connect-bootloader-instructions-1": "Din telefon kommer nu att starta om i läget starthanteraren
",
+ "connect-your-phone-instructions": "Anslut din telefon till din dator med en USB-kabel. Vi kommer automatiskt upptäcka din telefon för att installera /e/OS.",
+ "device-detection-instructions-2": "Ett popupp-fönster kommer synas på din telefon. Du behöver markera tillåt alltid från denna dator
innan du trycker ok.",
+ "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Exempel 3: och om du installerar /e/OS Android 11 bör det vara den senaste standardversionen av Android 10",
+ "activate-developer-options": "Aktivera utvecklaralternativ",
+ "activate-developer-options-instructions-1": "1. Öppna inställningsmenyn och skriv \"build\" i sökfältet.",
+ "activate-developer-options-instructions-2": "2. På nästa skärm letar du upp \"Build number\" och trycker 7 gånger på det.",
+ "activate-usb-debugging": "Aktivera USB-felsökning",
+ "activate-usb-debugging-instructions-2": "2. Nu bör du vara i \"Utvecklaralternativ\". Tryck nu på \"USB-felsökning\" för att aktivera det (på vissa enheter kan det kallas (Android-felsökning\").",
+ "activate-usb-debugging-instructions-1": "1. Gå tillbaka till inställningsmenyn och skriv \"USB-felsökning\" i sökfältet.",
+ "bootloader-to-recovery-manually": "Starthanterare till återställning",
+ "bootloader-to-recovery-manually-instructions": "Nu ska vi starta om din enhet i Återställningsläget. Följ nedan steg:",
+ "bootloader-to-recovery-manually-instructions-1": "1. Välj Återställningsläge
i starthanteraren genom att navigera med Volum upp och Volym ned",
+ "bootloader-to-recovery-manually-instructions-2": "2. Tryck på Av/På-knappen för att bekräfta",
+ "check-update-android-version": "Kontrollera och uppdatera din Androidversion",
+ "check-update-android-version-caution": "Varning: innan du fortsätter med installationen, kontrollera om den senaste Androidversionen finns tillgänglig för din enhet.",
+ "enable-usb-file-transfer-instructions-1": "Medan du fortfarande är inne i \"Utvecklaralternativ\" skrollar du ner för att hitta \"USB standardkonfiguration\" och trycker på det.",
+ "format-device": "Formatera enheten",
+ "format-device-instructions-1": "1. Välj fabriksåterställning
",
+ "format-device-instructions-2": "2. Välj alternativet Formatera data/Fabriksåterställning
",
+ "format-device-instructions-3": "3. Nästa skärm kommer visa en varning om att denna åtgärd inte kan göras ogjord",
+ "format-device-instructions-4": "4. Välj Formatera data
för att fortsätta",
+ "format-device-instructions-5": "5. Vänta medan formateringsprocessen slutförs",
+ "format-device-instructions-6": "6. Skärmen kommer nu gå tillbaka till skärmen Fabriksåterställning",
+ "help": "Hjälp",
+ "help-us-improve-the-tool": "Hjälp oss förbättra verktyget",
+ "help-us-improve-the-tool-instructions-1": "Vänligen betygsätt upplevelsen med /e/OS Installer.",
+ "help-us-improve-the-tool-instructions-2": "Har du några tankar om hur programvaran skulle kunna förbättras?",
+ "i-already-have-an-account": "Jag har redan ett konto",
+ "i-m-ready": "Jag är redo!",
+ "installation-complete": "Installationen är klar!",
+ "installation-complete-instructions-1": "Grattis! Medan din telefon startar bör du se loggan nedan. Detta tar tid, vänligen var tålmodig.",
+ "go-to-apply-update": "Nästan där!",
+ "go-to-apply-update-instructions-1": "1. Välj applicera uppdatering
.",
+ "go-to-apply-update-instructions-2": "2. Sedan Applicera uppdatering från adb
.",
+ "installation-complete-instructions-2": "Tips: följ instruktionerna på din telefon för att ställa in din enhet. Du kan nu föra över dina filer tillbaka till din telefon.",
+ "let-s-get-started-instruction-1": "Hela installationsprocessen kräver cirka 1 timme. Var\n tålmodig!",
+ "enable-usb-file-transfer-instructions-2": "Välj nu alternativet Filöverföring (på en del enheter kallas det \"MTP-läge (media transfer protocol)\").",
+ "format-device-instructions-7": "7. Tryck på bakåt
pilen och tryck på Nästa
",
+ "locking-instructions-3": "Klicka sedan på nästa",
+ "murena-workspace-account": "Murena Workspace-konto",
+ "murena-workspace-account-instructions": "Håll din data säker och synkronisera denna enheten med ditt personliga Murena Workspace-konto. 1 GB gratis och det finns betalplaner för mer utrymme.",
+ "navigator-detection": "Navigatorupptäckt",
+ "navigator-not-supported": "Din navigator stöds inte",
+ "navigator-not-supported-instructions": "Du kan använda följande webbläsare",
+ "neutral": "Neutral",
+ "unlocking-instructions-1-a": "Använd Av/På-knappen för att bekräfta.",
+ "android-version-not-supported": "Androidversionen är utdaterad",
+ "android-version-not-supported-title": "Din Androidverson {{android-version}}
stöds inte",
+ "android-version-not-supported-instructions": "Uppdatera ditt system till den version som är minimikravet {{android-version-required}}
",
+ "go-to-apply-update-instructions-3": "3. Enheten är nu i \"sideload\"-läge, du är nu redo för nästa steg.",
+ "let-s-get-started": "Nu sätter vi igång",
+ "let-s-get-started-instruction-2": "Du behöver minst 6 GB ledigt utrymme på din dator\n för att hämta och installera /e/OS. Se till att du har tillräckligt med ledigt utrymme på hårddisken.",
+ "let-s-get-started-instruction-3": "Se till att telefonens batteri har minst 50% laddning kvar innan du installerar /e/OS",
+ "let-s-get-started-instruction-4": "All data kommer raderas från din smarta telefon under installationen,\n vi rekommenderar att du tar en säkerhetskopia av din data.",
+ "let-s-get-started-instruction-5": "Det krävs en fungerande USB-datakabel. Laddkablar överför inte data\n och kommer inte att fungera! Vi rekommenderar USB 3.x eller senare.",
+ "let-s-get-started-instruction-title-1": "1. Frigör lite tid",
+ "let-s-get-started-instruction-title-2": "2. Frigör lagringsutrymme",
+ "let-s-get-started-instruction-title-3": "3. Ladda din telefon",
+ "let-s-get-started-instruction-title-4": "4. Säkerhetskopiera din data",
+ "let-s-get-started-instruction-title-5": "5. Ta en USB-datakabel",
+ "locking": "Låser",
+ "locking-instructions-1": "Din telefon frågar om att låsas upp. Välj lås starthanteraren
",
+ "locking-instructions-2": "Starta om din telefon om den inte startar om automatiskt",
+ "ready-to-install-e-os": "Du är nu redo att installera /e/OS.",
+ "recovery-to-bootloader": "Återställning till Starthanteraren",
+ "recovery-to-bootloader-instructions": "I huvudmenyn",
+ "recovery-to-bootloader-instructions-1": "1. Välj Avancerad
",
+ "recovery-to-bootloader-instructions-2": "2. Välj Starta om till starthanteraren
",
+ "satisfied": "Nöjd",
+ "send-to-e-team": "Skicka till Murena-teamet",
+ "sideload": "Installation pågår",
+ "sideload-instructions-1": "Skärmen kommer visa processen ... ",
+ "sideload-instructions-2": "Detta kan ta flera minuter, ge det lite tid.",
+ "sideload-instructions-3": "När installationen är klar kommer telefonen att gå tillbaka till huvudskärmen.",
+ "sideload-instructions-4": "Endast då kan du klicka på Nästa
.",
+ "skip": "Hoppa över",
+ "start": "Starta",
+ "this-might-take-some-time-please-be-patient": "Detta kan ta lite tid, vänligen ha tålamod",
+ "unlocking-instructions-1": "Din telefon frågaor om upplåsning. Välj lås upp starthanteraren
genom att navigera med Volym upp och Volym ned.",
+ "unlocking-instructions-2": "Starta om enheten om den inte startar om automatiskt.",
+ "bootloader-to-recovery-manually-instructions-3": "3. Vänta på att telefonen startar i återställning",
+ "go-to-apply-update-instructions-4": "Observera! Inför nästa steg kanske webbläsaren behöver återansluta till din telefon. Om ett popup-fönster dyker upp, välj din telefon från listan.",
+ "installing": "Installerar",
+ "unlocking-instructions-2-a": "Din enhet kommer starta om. Vänta till Starthanterarens skärm visas igen innan du går vidare till nästa steg",
+ "very-satisfied": "Mycket nöjd",
+ "unlocking-instructions-3": "Eftersom enheter helt återställs kommer du behöva aktivera USB-felsökning igen.",
+ "unlocking-instructions-4": "Hoppa över inställningen på telefonen och klicka på nästa",
+ "very-dissatisfied": "Mycket missnöjd",
+ "sign-up-free": "Registrera dig GRATIS"
}
diff --git a/app/public/assets/languages/tr.json b/app/public/assets/languages/tr.json
index 845989ed65c2fb242df94d5d94f3e995fd4b80f9..d0cd844271b458379d0a9365a450d6cff95bca58 100644
--- a/app/public/assets/languages/tr.json
+++ b/app/public/assets/languages/tr.json
@@ -1,22 +1,22 @@
{
- "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Örnek 1: /e/OS Android 12'yi yüklemeden önce, en son stok Android 12'ye güncellemelisiniz",
- "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Ex 2: veya /e/OS Android 11 yüklüyorsanız, en son stok Android 11'e güncellediğinizden emin olun",
- "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Ex 3: benzer şekilde, /e/OS Android 11 yüklüyorsanız, en son stok Android 10 olmalıdır",
- "activate-developer-options": "Geliştirici seçeneklerini etkinleştirin",
- "activate-developer-options-instructions-1": "1. Ayarlar menüsünü açın ve arama çubuğuna 'sürüm' yazın.",
- "activate-developer-options-instructions-2": "2. Bir sonraki ekranda 'Yapı numarası'nı bulun ve üzerine 7 kez dokunun.",
- "activate-usb-debugging": "USB Hata Ayıklamayı Etkinleştir",
- "activate-usb-debugging-instructions-1": "1. Ayarlar menüsüne geri dönün ve arama çubuğuna 'USB hata ayıklama' yazın.",
- "android-version-not-supported": "Android sürümü güncel değil",
- "android-version-not-supported-instructions": "Sisteminizi gereken minimum sürüme güncelleyin {{android-version-required}}
",
- "android-version-not-supported-title": "Android sürümünüz {{android-version}}
desteklenmiyor",
- "activate-usb-debugging-instructions-2": "2. Bu noktada 'Geliştirici seçenekleri ekranında' olmalısınız. Şimdi etkinleştirmek için 'USB hata ayıklama' üzerine dokunun (bazı cihazlarda 'Android Hata Ayıklama' olarak adlandırılır).",
- "bootloader-to-recovery-manually": "Önyükleyiciden kurtarmaya",
- "bootloader-to-recovery-manually-instructions": "Şimdi cihazınızı Kurtarma modunda yeniden başlatacağız. Lütfen aşağıdaki adımları takip edin:",
- "bootloader-to-recovery-manually-instructions-2": "2. Onaylamak için Güç düğmesine basın",
- "bootloader-to-recovery-manually-instructions-3": "3. Telefonunuzun kurtarma işleminde başlamasını bekleyin",
- "check-update-android-version": "Android sürümünüzü kontrol edin ve güncelleyin",
- "connect": "Bağlan",
- "connect-bootloader": "Önyükleyici bağlantısı",
- "bootloader-to-recovery-manually-instructions-1": "1. Önyükleyicide, Ses Açma ve Ses Kısma düğmelerini kullanarak kurtarma modunu
seçin"
+ "Ex 1: before installing /e/OS Android 12, you should update to the latest stock Android 12": "Örnek 1: /e/OS Android 12'yi yüklemeden önce, en son stok Android 12'ye güncellemelisiniz",
+ "Ex 2: or if you're installing /e/OS Android 11, make sure to update to the latest stock Android 11": "Ex 2: veya /e/OS Android 11 yüklüyorsanız, en son stok Android 11'e güncellediğinizden emin olun",
+ "Ex 3: similarly, if you're installing /e/OS Android 11, it should be the latest stock Android 10": "Ex 3: benzer şekilde, /e/OS Android 11 yüklüyorsanız, en son stok Android 10 olmalıdır",
+ "activate-developer-options": "Geliştirici seçeneklerini etkinleştirin",
+ "activate-developer-options-instructions-1": "1. Ayarlar menüsünü açın ve arama çubuğuna 'sürüm' yazın.",
+ "activate-developer-options-instructions-2": "2. Bir sonraki ekranda 'Yapı numarası'nı bulun ve üzerine 7 kez dokunun.",
+ "activate-usb-debugging": "USB Hata Ayıklamayı Etkinleştir",
+ "activate-usb-debugging-instructions-1": "1. Ayarlar menüsüne geri dönün ve arama çubuğuna 'USB hata ayıklama' yazın.",
+ "android-version-not-supported": "Android sürümü güncel değil",
+ "android-version-not-supported-instructions": "Sisteminizi gereken minimum sürüme güncelleyin {{android-version-required}}
",
+ "android-version-not-supported-title": "Android sürümünüz {{android-version}}
desteklenmiyor",
+ "activate-usb-debugging-instructions-2": "2. Bu noktada 'Geliştirici seçenekleri ekranında' olmalısınız. Şimdi etkinleştirmek için 'USB hata ayıklama' üzerine dokunun (bazı cihazlarda 'Android Hata Ayıklama' olarak adlandırılır).",
+ "bootloader-to-recovery-manually": "Önyükleyiciden kurtarmaya",
+ "bootloader-to-recovery-manually-instructions": "Şimdi cihazınızı Kurtarma modunda yeniden başlatacağız. Lütfen aşağıdaki adımları takip edin:",
+ "bootloader-to-recovery-manually-instructions-2": "2. Onaylamak için Güç düğmesine basın",
+ "bootloader-to-recovery-manually-instructions-3": "3. Telefonunuzun kurtarma işleminde başlamasını bekleyin",
+ "check-update-android-version": "Android sürümünüzü kontrol edin ve güncelleyin",
+ "connect": "Bağlan",
+ "connect-bootloader": "Önyükleyici bağlantısı",
+ "bootloader-to-recovery-manually-instructions-1": "1. Önyükleyicide, Ses Açma ve Ses Kısma düğmelerini kullanarak kurtarma modunu
seçin"
}
diff --git a/app/public/css/loader.css b/app/public/css/loader.css
index 1f8e84aaece1954efe250881af3f8b2924418fd9..56c05e1b4fb2b504d93015910c2f7ab3ac549466 100644
--- a/app/public/css/loader.css
+++ b/app/public/css/loader.css
@@ -1,21 +1,25 @@
button.next {
- display: inline-flex;
- align-items: center;
- justify-content: center;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
}
.btn-loader {
- border: 2px solid #d4d4d4;
- border-top: 2px solid white;
- border-radius: 50%;
- width: 12px;
- height: 12px;
- margin-left: 10px;
- animation: spin 1s linear infinite;
- display: none;
+ border: 2px solid #d4d4d4;
+ border-top: 2px solid white;
+ border-radius: 50%;
+ width: 12px;
+ height: 12px;
+ margin-left: 10px;
+ animation: spin 1s linear infinite;
+ display: none;
}
@keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
-}
\ No newline at end of file
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
diff --git a/app/public/css/styles.css b/app/public/css/styles.css
index 3d6230b200fbcb07369caeac2b06f319996cc210..7a1c98d03e03ae2cffaf492c0fc07e5383f80383 100644
--- a/app/public/css/styles.css
+++ b/app/public/css/styles.css
@@ -1,210 +1,219 @@
@import "theme.css";
-
#compatibility-check {
- display: none;
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- background-color: #fff;
- padding: 20px;
- border: 2px solid #ccc;
- z-index: 1000;
+ display: none;
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background-color: #fff;
+ padding: 20px;
+ border: 2px solid #ccc;
+ z-index: 1000;
}
button.connect {
- background: var(--success-color);
- color: var(--button-text-color);
- border: none;
+ background: var(--success-color);
+ color: var(--button-text-color);
+ border: none;
}
button.next {
- background: var(--button-color);
- color: var(--button-text-color);
- border: none;
+ background: var(--button-color);
+ color: var(--button-text-color);
+ border: none;
}
button.next:disabled {
- background: rgba(2, 127, 254, 0.6);
- cursor: auto;
+ background: rgba(2, 127, 254, 0.6);
+ cursor: auto;
}
#error-message {
- color: red;
+ color: red;
}
/* */
#banner {
- top: 0;
- position: fixed;
- width: 100%;
+ top: 0;
+ position: fixed;
+ width: 100%;
}
#top-banner {
- background: var(--top-banner-color);
- color: var(--white);
- height: 50px;
- display: flex;
- width: 100%;
- flex-wrap: wrap;
- gap: 10px;
- align-content: center;
- justify-content: center;
+ background: var(--top-banner-color);
+ color: var(--white);
+ height: 50px;
+ display: flex;
+ width: 100%;
+ flex-wrap: wrap;
+ gap: 10px;
+ align-content: center;
+ justify-content: center;
}
#sub-banner {
- display: flex;
- justify-content: space-between;
- padding: 5px 10px;
+ display: flex;
+ justify-content: space-between;
+ padding: 5px 10px;
}
#error-message-state {
- max-height: 100px;
- overflow: auto;
- padding: 5px;
- border: 1px solid var(--top-banner-color);
- background-color:#fff;
-}
-#donate, #help {
- display: flex;
- align-items: center;
- gap : 8px;
- padding: 0.2rem 1.5rem;
-}
-#donate img, #help img{
- width: 24px;
- height: 24px;
-}
-#donate{
- background: var(--green);
- border: var(--green);
- color: var(--white);
-}
-#help{
- background: transparent;
- border-color: var(--blue);
- color: var(--blue);
+ max-height: 100px;
+ overflow: auto;
+ padding: 5px;
+ border: 1px solid var(--top-banner-color);
+ background-color: #fff;
+}
+#donate,
+#help {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 0.2rem 1.5rem;
+}
+#donate img,
+#help img {
+ width: 24px;
+ height: 24px;
+}
+#donate {
+ background: var(--green);
+ border: var(--green);
+ color: var(--white);
+}
+#help {
+ background: transparent;
+ border-color: var(--blue);
+ color: var(--blue);
}
/* */
/* */
#process-ctn {
- background: linear-gradient(to bottom, var(--top-background-color) 500px, transparent 500px);
- padding-top: 250px;
- position: relative;
- width: 100%;
+ background: linear-gradient(
+ to bottom,
+ var(--top-background-color) 500px,
+ transparent 500px
+ );
+ padding-top: 250px;
+ position: relative;
+ width: 100%;
}
.ready-to-install-e-os {
- color : var(--info-color);
- font-size: 28px;
- display: none;
+ color: var(--info-color);
+ font-size: 28px;
+ display: none;
}
#logo-ctn {
- max-width: 780px;
- margin:auto;
- display: flex;
- gap: 16px;
- color : #F7F7F7;
- align-items: center;
+ max-width: 780px;
+ margin: auto;
+ display: flex;
+ gap: 16px;
+ color: #f7f7f7;
+ align-items: center;
}
#logo {
- max-width: 80px;
+ max-width: 80px;
}
/* */
/* */
.card {
- scroll-margin-top: 65px;
- box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);
- max-width: 780px;
- border-radius: 6px;
- background: var(--white);
- margin: 25px auto 50px auto;
- padding: 32px;
+ scroll-margin-top: 65px;
+ box-shadow:
+ 0 1px 3px 0 rgba(0, 0, 0, 0.1),
+ 0 1px 2px -1px rgba(0, 0, 0, 0.1);
+ max-width: 780px;
+ border-radius: 6px;
+ background: var(--white);
+ margin: 25px auto 50px auto;
+ padding: 32px;
}
.card-header {
- font-size: 24px;
- font-family: 'Century Gothic';
- font-weight: 600;
+ font-size: 24px;
+ font-family: "Century Gothic";
+ font-weight: 600;
}
-.card-body, .large-padding {
- padding-top: 16px;
- padding-bottom: 16px;
+.card-body,
+.large-padding {
+ padding-top: 16px;
+ padding-bottom: 16px;
}
.card-footer {
- text-align : right;
+ text-align: right;
}
.flashing.done progress {
- -webkit-appearance: none;
- height: 2px;
+ -webkit-appearance: none;
+ height: 2px;
}
.flashing.done progress::-webkit-progress-bar {
- -webkit-appearance: none;
- background-color: var(--green);
+ -webkit-appearance: none;
+ background-color: var(--green);
}
/* */
.instruction-title {
- font-size: 18px;
- font-weight: 600;
+ font-size: 18px;
+ font-weight: 600;
}
.normal-padding {
- margin-bottom : 20px;
- margin-top : 20px;
+ margin-bottom: 20px;
+ margin-top: 20px;
}
.enable-usb-file-transfer .instruction-img {
- max-width: 225px;
+ max-width: 225px;
}
-.device-detection .instruction-img, .connect-your-phone .instruction-img {
- max-width: 300px;
+.device-detection .instruction-img,
+.connect-your-phone .instruction-img {
+ max-width: 300px;
}
.activate-developer-options .instruction-img,
.activate-usb-debugging .instruction-img,
-.connect-your-phone .instruction-img {
- max-width: 350px;
+.connect-your-phone .instruction-img {
+ max-width: 350px;
}
#overlay-background {
- position: absolute;
- background: #0000004f;
- display: flex;
- align-items: center;
- justify-content: center;
- top: 0;
- left: 0;
- right: 0;
- bottom:0;
+ position: absolute;
+ background: #0000004f;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
}
progress {
- height: 3px;
- width: 50%;
- min-width: 300px;
+ height: 3px;
+ width: 50%;
+ min-width: 300px;
}
progress[value] {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- border: none;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ border: none;
}
progress[value]::-webkit-progress-bar {
- background-color: #d0d0d0;
+ background-color: #d0d0d0;
}
progress[value]::-webkit-progress-value {
- background-color: var(--downloading-color);
+ background-color: var(--downloading-color);
}
progress[value].success::-webkit-progress-value {
- background-color: var(--green);
+ background-color: var(--green);
}
/* */
/* */
.let-s-get-started .instruction-ctn {
- padding : 16px 0;
- display : flex;
- align-items: center;
- gap : 24px;
+ padding: 16px 0;
+ display: flex;
+ align-items: center;
+ gap: 24px;
}
.let-s-get-started .instruction-title {
- padding-bottom: 8px;
+ padding-bottom: 8px;
}
/* */
.navigator-not-supported .instructions-ctn {
- display: grid;
- grid-template-columns: repeat(4, 1fr);
- gap: 22px;
- text-align:center;
- font-size:14px;
- padding: 16px 0;
-}
\ No newline at end of file
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 22px;
+ text-align: center;
+ font-size: 14px;
+ padding: 16px 0;
+}
diff --git a/app/public/css/theme.css b/app/public/css/theme.css
index d9802d33bff3e0f142a2458beff0e7550dddd2e5..0261db803e982ca809558f6160776f3b59eabc86 100644
--- a/app/public/css/theme.css
+++ b/app/public/css/theme.css
@@ -1,94 +1,98 @@
-@font-face {
- font-family: "Century Gothic";
- src: url("../assets/fonts/century-gothic/Century-Gothic.ttf") format("truetype");
-}
-@font-face {
- font-family: "Century Gothic Bold";
- src: url("../assets/fonts/century-gothic/Century-Gothic.ttf") format("truetype");
-}
-:root {
- --top-banner-color: #191823;
- --top-background-color: #0f0f0f;
- --background-color: #f7f7f7;
- --text-color: #111111;
- --info-color: #027ffe;
- --base-color: #dedee5;
- --secondary-color: #898989;
- --base-color-alt: #f5f5f7;
- --blue: #2a7ae2;
- --white: white;
- --green: #00b13c;
- --success-color: #61CE70;
- --downloading-color: #027ffe;
- --button-color: #027ffe;
- --button-text-color: white;
- --warning-background-color: #fff1c9;
- --warning-text-color: #795917;
- --info-background-color: #cbe9ee;
- --info-text-color: #104a55;
-}
-html, body {
- margin: 0px;
- background: var(--background-color);
- font-family: 'Century Gothic', 'Lato';
- font-size : 14px;
-}
-button {
- border-radius: 100px;
- padding: 0.4rem 1.5rem;
- cursor: pointer;
- transition: background-color 0.25s ease-in-out;
-}
-kbd {
- padding: .2rem .4rem;
- font-size: 87.5%;
- color: #fff;
- background-color: #212529;
- border-radius: .2rem;
-}
-code {
- border: 1px solid #e8e8e8;
- border-radius: 3px;
- background-color: #eef;
- font-size: 87.5%;
- color: #e83e8c;
- word-wrap: break-word;
-}
-.warning {
- background: var(--warning-background-color);
- color: var(--warning-text-color);
-}
-.info {
- background: var(--info-background-color);
- color: var(--info-text-color);
-}
-.warning, .info {
- padding: 0.625rem;
- border-radius: 4px;
-}
-.secondary {
- color : var(--secondary-color);
-}
-.text-center {
- text-align: center;
-}
-.inactive {
- display: none !important;
-}
-
-.active {
- display: block !important;
-}
-.icon {
- width: 2.5rem;
- height: 2.5rem;
-}
-.gap-4 {
- gap: 1.5rem !important;
-}
-.flex {
- display: flex;
-}
-.align-items-center {
- align-items: center;
-}
\ No newline at end of file
+@font-face {
+ font-family: "Century Gothic";
+ src: url("../assets/fonts/century-gothic/Century-Gothic.ttf")
+ format("truetype");
+}
+@font-face {
+ font-family: "Century Gothic Bold";
+ src: url("../assets/fonts/century-gothic/Century-Gothic.ttf")
+ format("truetype");
+}
+:root {
+ --top-banner-color: #191823;
+ --top-background-color: #0f0f0f;
+ --background-color: #f7f7f7;
+ --text-color: #111111;
+ --info-color: #027ffe;
+ --base-color: #dedee5;
+ --secondary-color: #898989;
+ --base-color-alt: #f5f5f7;
+ --blue: #2a7ae2;
+ --white: white;
+ --green: #00b13c;
+ --success-color: #61ce70;
+ --downloading-color: #027ffe;
+ --button-color: #027ffe;
+ --button-text-color: white;
+ --warning-background-color: #fff1c9;
+ --warning-text-color: #795917;
+ --info-background-color: #cbe9ee;
+ --info-text-color: #104a55;
+}
+html,
+body {
+ margin: 0px;
+ background: var(--background-color);
+ font-family: "Century Gothic", "Lato";
+ font-size: 14px;
+}
+button {
+ border-radius: 100px;
+ padding: 0.4rem 1.5rem;
+ cursor: pointer;
+ transition: background-color 0.25s ease-in-out;
+}
+kbd {
+ padding: 0.2rem 0.4rem;
+ font-size: 87.5%;
+ color: #fff;
+ background-color: #212529;
+ border-radius: 0.2rem;
+}
+code {
+ border: 1px solid #e8e8e8;
+ border-radius: 3px;
+ background-color: #eef;
+ font-size: 87.5%;
+ color: #e83e8c;
+ word-wrap: break-word;
+}
+.warning {
+ background: var(--warning-background-color);
+ color: var(--warning-text-color);
+}
+.info {
+ background: var(--info-background-color);
+ color: var(--info-text-color);
+}
+.warning,
+.info {
+ padding: 0.625rem;
+ border-radius: 4px;
+}
+.secondary {
+ color: var(--secondary-color);
+}
+.text-center {
+ text-align: center;
+}
+.inactive {
+ display: none !important;
+}
+
+.active {
+ display: block !important;
+}
+.icon {
+ width: 2.5rem;
+ height: 2.5rem;
+}
+.gap-4 {
+ gap: 1.5rem !important;
+}
+.flex {
+ display: flex;
+}
+.align-items-center {
+ align-items: center;
+}
diff --git a/app/public/resources/-Nord.json b/app/public/resources/-Nord.json
index ea93fc8fc018bff0de2fdff6fbe623714003678f..8bd275beb687c224f247cb46f1bf04ef7165e5e6 100644
--- a/app/public/resources/-Nord.json
+++ b/app/public/resources/-Nord.json
@@ -6,10 +6,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "oem unlock"
- ],
+ "command": ["connect bootloader", "oem unlock"],
"needUserGesture": true
},
{
@@ -69,10 +66,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "reboot"
- ],
+ "command": ["connect bootloader", "reboot"],
"needUserGesture": true
},
{
diff --git a/app/public/resources/FP3.json b/app/public/resources/FP3.json
index b4a50a9fc433efd1bb8c03a2432a9c9309d63b35..3e3bda91b56fef485a51b7f1a9cb75091db5941b 100644
--- a/app/public/resources/FP3.json
+++ b/app/public/resources/FP3.json
@@ -3,7 +3,7 @@
{
"mode": "bootloader",
"id": "connect-bootloader",
- "command": ["connect bootloader","oem unlock unlocked"],
+ "command": ["connect bootloader", "oem unlock unlocked"],
"needUserGesture": true
},
{
@@ -31,7 +31,7 @@
},
{
"id": "flashing",
- "command" : [
+ "command": [
"flash modem_a modem.img",
"flash modem_a modem.img",
"flash modem_b modem.img",
diff --git a/app/public/resources/FP4-safe.json b/app/public/resources/FP4-safe.json
index 6646670ab59ecdee6ce9ad9815a973253b64911d..1f267bbc34bbd55796aa33cc50dc2fe9a2f629aa 100644
--- a/app/public/resources/FP4-safe.json
+++ b/app/public/resources/FP4-safe.json
@@ -110,7 +110,8 @@
"flash core_nhlos_a core_nhlos.img --set-active=a",
"erase userdata",
"erase metadata",
- "reboot"]
+ "reboot"
+ ]
},
{
"id": "murena-workspace-account",
@@ -124,7 +125,7 @@
{
"name": "FP4 installer",
"unzip": true,
- "path": "https://images.ecloud.global/official/FP4/IMG-e-latest-u-official-FP4.zip"
+ "path": "https://images.ecloud.global/official/FP4/IMG-e-latest-t-official-FP4.zip"
}
]
}
diff --git a/app/public/resources/FP4.json b/app/public/resources/FP4.json
index fa9e4d3e21c02fd9ad5bbc83ebe4cd980d6abfae..036fcfb7bf47e042d6ffa0b66ab2ec75900fa808 100644
--- a/app/public/resources/FP4.json
+++ b/app/public/resources/FP4.json
@@ -64,54 +64,55 @@
{
"id": "flashing",
"command": [
- "flash bluetooth_a bluetooth.img",
- "flash bluetooth_b bluetooth.img",
- "flash devcfg_a devcfg.img",
- "flash devcfg_b devcfg.img",
- "flash dsp_a dsp.img",
- "flash dsp_b dsp.img",
- "flash modem_a modem.img",
- "flash modem_b modem.img",
- "flash xbl_a xbl.img",
- "flash xbl_b xbl.img",
- "flash tz_a tz.img",
- "flash tz_b tz.img",
- "flash hyp_a hyp.img",
- "flash hyp_b hyp.img",
- "flash keymaster_a keymaster.img",
- "flash keymaster_b keymaster.img",
- "flash abl_a abl.img",
- "flash abl_b abl.img",
- "flash boot_a boot.img",
- "flash boot_b boot.img",
- "flash recovery_a recovery.img",
- "flash recovery_b recovery.img",
- "flash dtbo_a dtbo.img",
- "flash dtbo_b dtbo.img",
- "flash vbmeta_system_a vbmeta_system.img",
- "flash vbmeta_system_b vbmeta_system.img",
- "flash vbmeta_a vbmeta.img",
- "flash vbmeta_b vbmeta.img",
- "flash super super.img",
- "flash aop_a aop.img",
- "flash aop_b aop.img",
- "flash featenabler_a featenabler.img",
- "flash featenabler_b featenabler.img",
- "flash imagefv_a imagefv.img",
- "flash imagefv_b imagefv.img",
- "flash multiimgoem_a multiimgoem.img",
- "flash multiimgoem_b multiimgoem.img",
- "flash qupfw_a qupfw.img",
- "flash qupfw_b qupfw.img",
- "flash uefisecapp_a uefisecapp.img",
- "flash uefisecapp_b uefisecapp.img",
- "flash xbl_config_a xbl_config.img",
- "flash xbl_config_b xbl_config.img",
- "flash core_nhlos_b core_nhlos.img",
- "flash core_nhlos_a core_nhlos.img --set-active=a",
- "erase userdata",
- "erase metadata",
- "flashing lock"]
+ "flash bluetooth_a bluetooth.img",
+ "flash bluetooth_b bluetooth.img",
+ "flash devcfg_a devcfg.img",
+ "flash devcfg_b devcfg.img",
+ "flash dsp_a dsp.img",
+ "flash dsp_b dsp.img",
+ "flash modem_a modem.img",
+ "flash modem_b modem.img",
+ "flash xbl_a xbl.img",
+ "flash xbl_b xbl.img",
+ "flash tz_a tz.img",
+ "flash tz_b tz.img",
+ "flash hyp_a hyp.img",
+ "flash hyp_b hyp.img",
+ "flash keymaster_a keymaster.img",
+ "flash keymaster_b keymaster.img",
+ "flash abl_a abl.img",
+ "flash abl_b abl.img",
+ "flash boot_a boot.img",
+ "flash boot_b boot.img",
+ "flash recovery_a recovery.img",
+ "flash recovery_b recovery.img",
+ "flash dtbo_a dtbo.img",
+ "flash dtbo_b dtbo.img",
+ "flash vbmeta_system_a vbmeta_system.img",
+ "flash vbmeta_system_b vbmeta_system.img",
+ "flash vbmeta_a vbmeta.img",
+ "flash vbmeta_b vbmeta.img",
+ "flash super super.img",
+ "flash aop_a aop.img",
+ "flash aop_b aop.img",
+ "flash featenabler_a featenabler.img",
+ "flash featenabler_b featenabler.img",
+ "flash imagefv_a imagefv.img",
+ "flash imagefv_b imagefv.img",
+ "flash multiimgoem_a multiimgoem.img",
+ "flash multiimgoem_b multiimgoem.img",
+ "flash qupfw_a qupfw.img",
+ "flash qupfw_b qupfw.img",
+ "flash uefisecapp_a uefisecapp.img",
+ "flash uefisecapp_b uefisecapp.img",
+ "flash xbl_config_a xbl_config.img",
+ "flash xbl_config_b xbl_config.img",
+ "flash core_nhlos_b core_nhlos.img",
+ "flash core_nhlos_a core_nhlos.img --set-active=a",
+ "erase userdata",
+ "erase metadata",
+ "flashing lock"
+ ]
},
{
"id": "locking-fp4",
@@ -156,7 +157,7 @@
{
"name": "FP4 installer",
"unzip": true,
- "path": "https://images.ecloud.global/official/FP4/IMG-e-latest-u-official-FP4.zip"
+ "path": "https://images.ecloud.global/official/FP4/IMG-e-latest-t-official-FP4.zip"
}
]
}
diff --git a/app/public/resources/GS290.json b/app/public/resources/GS290.json
index f8cd8cb95817baecaff5ba2877b3dbf884f4ff21..281dfe4ef7e0d2ba6a68b07a9143cc9d1fb5cd06 100644
--- a/app/public/resources/GS290.json
+++ b/app/public/resources/GS290.json
@@ -1,9 +1,9 @@
{
"steps": [
- {
+ {
"mode": "bootloader",
"id": "connect-bootloader",
- "command": ["connect bootloader","flashing unlock unlocked"],
+ "command": ["connect bootloader", "flashing unlock unlocked"],
"needUserGesture": true
},
{
diff --git a/app/public/resources/OnePlus7.json b/app/public/resources/OnePlus7.json
index 6a9562a41e43f0c571c424d59287df09d3b4c16f..747b217c3f0dfc8ff1709094445fb28591b57278 100644
--- a/app/public/resources/OnePlus7.json
+++ b/app/public/resources/OnePlus7.json
@@ -6,10 +6,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "oem unlock"
- ],
+ "command": ["connect bootloader", "oem unlock"],
"needUserGesture": true
},
{
@@ -65,10 +62,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "reboot"
- ],
+ "command": ["connect bootloader", "reboot"],
"needUserGesture": true
},
{
diff --git a/app/public/resources/OnePlus7Pro.json b/app/public/resources/OnePlus7Pro.json
index f123030a45affc2f65ffc7e40ae8bf5cad01dffb..f427d92b978c1404b084031a1539e83cd032047b 100644
--- a/app/public/resources/OnePlus7Pro.json
+++ b/app/public/resources/OnePlus7Pro.json
@@ -6,10 +6,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "oem unlock"
- ],
+ "command": ["connect bootloader", "oem unlock"],
"needUserGesture": true
},
{
@@ -65,10 +62,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "reboot"
- ],
+ "command": ["connect bootloader", "reboot"],
"needUserGesture": true
},
{
diff --git a/app/public/resources/OnePlus7T.json b/app/public/resources/OnePlus7T.json
index 4365250a4c42c3ce21f99b02156c63fe53954398..6c607036c9705613bd7ac7b8d214c839a10ed1b7 100644
--- a/app/public/resources/OnePlus7T.json
+++ b/app/public/resources/OnePlus7T.json
@@ -6,10 +6,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "oem unlock"
- ],
+ "command": ["connect bootloader", "oem unlock"],
"needUserGesture": true
},
{
@@ -65,10 +62,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "reboot"
- ],
+ "command": ["connect bootloader", "reboot"],
"needUserGesture": true
},
{
diff --git a/app/public/resources/OnePlus8.json b/app/public/resources/OnePlus8.json
index caf17ff1f42ebcac5ab3e7e4a99ee8ee4125ac3a..a8da9f43e8db1659f8752781eb66bd5f7de35ae1 100644
--- a/app/public/resources/OnePlus8.json
+++ b/app/public/resources/OnePlus8.json
@@ -6,10 +6,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "oem unlock"
- ],
+ "command": ["connect bootloader", "oem unlock"],
"needUserGesture": true
},
{
@@ -65,10 +62,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "reboot"
- ],
+ "command": ["connect bootloader", "reboot"],
"needUserGesture": true
},
{
diff --git a/app/public/resources/OnePlus8Pro.json b/app/public/resources/OnePlus8Pro.json
index db34b444ee67a3baae695e207c4d37f6924f14d0..fbb5890bd06c9b50f1a2f6acbcbfbafee415f506 100644
--- a/app/public/resources/OnePlus8Pro.json
+++ b/app/public/resources/OnePlus8Pro.json
@@ -6,10 +6,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "oem unlock"
- ],
+ "command": ["connect bootloader", "oem unlock"],
"needUserGesture": true
},
{
@@ -65,10 +62,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "reboot"
- ],
+ "command": ["connect bootloader", "reboot"],
"needUserGesture": true
},
{
diff --git a/app/public/resources/Teracube_2e.json b/app/public/resources/Teracube_2e.json
index 1a4ecf878976486ae16e8d14d8f078518dc3e551..be88089a099604e3b44d657778ca56e07475e462 100644
--- a/app/public/resources/Teracube_2e.json
+++ b/app/public/resources/Teracube_2e.json
@@ -1,6 +1,6 @@
{
"UNUSED___security_patch_level": "2020-04-05",
- "description" : "Teracube 2e (2020)",
+ "description": "Teracube 2e (2020)",
"steps": [
{
"mode": "bootloader",
@@ -13,10 +13,10 @@
"needUserGesture": true
},
{
- "id": "flashing",
+ "id": "flashing",
"command": [
"erase userdata",
-
+
"flash preloader preloader_zirconia.bin",
"flash lk lk.img",
"flash md1img md1img.img",
@@ -48,9 +48,9 @@
],
"folder": [
{
- "path": "https://images.ecloud.global/official/zirconia/IMG-e-latest-s-official-zirconia.zip",
- "name": "Teracube 2e (2020) installer",
- "unzip": true
+ "path": "https://images.ecloud.global/official/zirconia/IMG-e-latest-s-official-zirconia.zip",
+ "name": "Teracube 2e (2020) installer",
+ "unzip": true
}
]
}
diff --git a/app/public/resources/coral.json b/app/public/resources/coral.json
index 52a28c4830e4977f0974a82874b78fb0aecaca68..2634a5aa16c3e67a4cc02bc6bbeffc0ae1c9f8fc 100644
--- a/app/public/resources/coral.json
+++ b/app/public/resources/coral.json
@@ -6,7 +6,7 @@
},
{
"id": "connect-bootloader",
- "command": ["connect bootloader", "flashing unlock unlocked" ],
+ "command": ["connect bootloader", "flashing unlock unlocked"],
"needUserGesture": true
},
{
@@ -16,10 +16,7 @@
},
{
"id": "flashing",
- "command": [
- "flash dtbo dtbo.img",
- "flash boot recovery.img"
- ]
+ "command": ["flash dtbo dtbo.img", "flash boot recovery.img"]
},
{
"id": "bootloader-to-recovery-manually",
@@ -43,10 +40,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "reboot"
- ],
+ "command": ["connect bootloader", "reboot"],
"needUserGesture": true
},
{
diff --git a/app/public/resources/emerald-safe.json b/app/public/resources/emerald-safe.json
index 5587166fc3c03ecf1cfb791b2d1f68c63c8cf6fc..853abb0e66139e7567fcdd31f2be7956e04cef77 100644
--- a/app/public/resources/emerald-safe.json
+++ b/app/public/resources/emerald-safe.json
@@ -1,5 +1,5 @@
{
- "description" : "Teracube 2e (2021 emerald) Safe",
+ "description": "Teracube 2e (2021 emerald) Safe",
"steps": [
{
"mode": "bootloader",
@@ -12,9 +12,8 @@
"needUserGesture": true
},
{
- "id": "flashing",
+ "id": "flashing",
"command": [
-
"erase userdata",
"format md_udc",
"flash boot_a boot.img",
diff --git a/app/public/resources/emerald.json b/app/public/resources/emerald.json
index 4576d107de41701bfb7ddaabb73dacd5c9e3e524..7ca01e0129938ea1943785d250237fd172daaced 100644
--- a/app/public/resources/emerald.json
+++ b/app/public/resources/emerald.json
@@ -1,6 +1,6 @@
{
"UNUSED___security_patch_level": "2020-04-05",
- "description" : "Teracube 2e (2021 emerald)",
+ "description": "Teracube 2e (2021 emerald)",
"steps": [
{
"mode": "bootloader",
@@ -13,9 +13,8 @@
"needUserGesture": true
},
{
- "id": "flashing",
+ "id": "flashing",
"command": [
-
"erase userdata",
"format md_udc",
"flash boot_a boot.img",
@@ -56,9 +55,9 @@
],
"folder": [
{
- "path": "https://images.ecloud.global/official/emerald/IMG-e-latest-s-official-emerald.zip",
- "name": "Teracube 2e (2021 emerald) installer",
- "unzip": true
+ "path": "https://images.ecloud.global/official/emerald/IMG-e-latest-s-official-emerald.zip",
+ "name": "Teracube 2e (2021 emerald) installer",
+ "unzip": true
}
]
}
diff --git a/app/public/resources/flame.json b/app/public/resources/flame.json
index 18557d829c36e591b4453fa42a782c9efb038f94..b56188dcbf3683a03cefcd3b44d05d89f5bd3009 100644
--- a/app/public/resources/flame.json
+++ b/app/public/resources/flame.json
@@ -6,7 +6,7 @@
},
{
"id": "connect-bootloader",
- "command": ["connect bootloader", "flashing unlock unlocked" ],
+ "command": ["connect bootloader", "flashing unlock unlocked"],
"needUserGesture": true
},
{
@@ -16,10 +16,7 @@
},
{
"id": "flashing",
- "command": [
- "flash dtbo dtbo.img",
- "flash boot recovery.img"
- ]
+ "command": ["flash dtbo dtbo.img", "flash boot recovery.img"]
},
{
"id": "bootloader-to-recovery-manually",
@@ -43,10 +40,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "reboot"
- ],
+ "command": ["connect bootloader", "reboot"],
"needUserGesture": true
},
{
diff --git a/app/public/resources/redfin.json b/app/public/resources/redfin.json
index 38f909bce70356cf012012be87d356f48f4af659..ca9fd8ec45abea5bca75c9d811663b18fad55050 100644
--- a/app/public/resources/redfin.json
+++ b/app/public/resources/redfin.json
@@ -6,7 +6,7 @@
},
{
"id": "connect-bootloader",
- "command": ["connect bootloader", "flashing unlock unlocked" ],
+ "command": ["connect bootloader", "flashing unlock unlocked"],
"needUserGesture": true
},
{
diff --git a/app/public/resources/shiba.json b/app/public/resources/shiba.json
index b41bb830bceddd55d05dd9ce0c25ce7c5079d96e..f40c91fc66cdb12bca96dff2242fe548409c9365 100644
--- a/app/public/resources/shiba.json
+++ b/app/public/resources/shiba.json
@@ -87,5 +87,3 @@
}
]
}
-
-
diff --git a/app/public/resources/sunfish.json b/app/public/resources/sunfish.json
index b2a793c30f7409f453aa710fc405e48989504a32..5febd2f7cfd6781d6df243f0119d0fcf8b74d6c2 100644
--- a/app/public/resources/sunfish.json
+++ b/app/public/resources/sunfish.json
@@ -6,7 +6,7 @@
},
{
"id": "connect-bootloader",
- "command": ["connect bootloader", "flashing unlock unlocked" ],
+ "command": ["connect bootloader", "flashing unlock unlocked"],
"needUserGesture": true
},
{
@@ -16,10 +16,7 @@
},
{
"id": "flashing",
- "command": [
- "flash dtbo dtbo.img",
- "flash boot recovery.img"
- ]
+ "command": ["flash dtbo dtbo.img", "flash boot recovery.img"]
},
{
"id": "bootloader-to-recovery-manually",
@@ -43,10 +40,7 @@
},
{
"id": "connect-bootloader",
- "command": [
- "connect bootloader",
- "reboot"
- ],
+ "command": ["connect bootloader", "reboot"],
"needUserGesture": true
},
{
diff --git a/app/public/resources/tetris.json b/app/public/resources/tetris.json
index 0486ebba6bb576f61263a68cc2eec11e5618c638..2d619b2234b68d3eb5152963ec07d81ec07b7fce 100644
--- a/app/public/resources/tetris.json
+++ b/app/public/resources/tetris.json
@@ -1,20 +1,20 @@
{
"android": 14,
"steps": [
- {
+ {
"mode": "bootloader",
"id": "connect-bootloader",
- "command": ["connect bootloader","flashing unlock"],
+ "command": ["connect bootloader", "flashing unlock"],
"needUserGesture": true
},
{
"id": "unlocking-gs290",
"needUserGesture": true
},
- {
+ {
"mode": "bootloader",
"id": "connect-bootloader",
- "command": ["connect bootloader","flashing unlock_critical"],
+ "command": ["connect bootloader", "flashing unlock_critical"],
"needUserGesture": true
},
{
diff --git a/app/src/before-leave-app.js b/app/src/before-leave-app.js
index bbd81c38378b9a05f47b107c1194144f9811020d..04b72ff150ed86e40da007f740c4998db6d258e2 100644
--- a/app/src/before-leave-app.js
+++ b/app/src/before-leave-app.js
@@ -1,3 +1,3 @@
-window.addEventListener('beforeunload', function (event) {
- event.preventDefault();
-});
\ No newline at end of file
+window.addEventListener("beforeunload", function (event) {
+ event.preventDefault();
+});
diff --git a/app/src/controller.manager.js b/app/src/controller.manager.js
index 73a05a4ee45c3317d12bd8af312c792ff08f09fc..990540e1873f99347d8c57606f468dd10b210b58 100644
--- a/app/src/controller.manager.js
+++ b/app/src/controller.manager.js
@@ -1,371 +1,428 @@
-import {DeviceManager} from "./controller/device.manager.js";
-import {Command} from "./controller/device/command.class.js";
-import {Step} from "./controller/utils/step.class.js";
-import {WDebug} from "./debug.js";
-/*
-* Class to manage process
-* Check and display the steps, interact with deviceManager
-*/
-export class Controller {
- constructor() {
- this.steps = [
- new Step("let-s-get-started", undefined, true),
- new Step("connect-your-phone", undefined, true),
- new Step("activate-developer-options", undefined, true),
- new Step("activate-oem-unlock", undefined, true),
- new Step("activate-usb-debugging", undefined, true),
- new Step("enable-usb-file-transfer", undefined, true),
- new Step("device-detection", 'connect adb', true),
- ];
- this.currentIndex = 0;
- }
-
-
- async init(view) {
- this.deviceManager = new DeviceManager();
- await this.deviceManager.init();
- this.view = view;
- }
-
- async next() {
-
- let current = this.steps[this.currentIndex];
- let next = this.steps[this.currentIndex + 1];
-
- WDebug.log("Controller Manager Next", next);
-
- if (next) {
- //K1ZFP check this
- if (next.mode) { //if next step require another mode [adb|fastboot|bootloader]
- if (this.deviceManager.isConnected() && !this.inInMode(next.mode)) {
- //we need reboot
- await this.deviceManager.reboot(next.mode);
- }
- if (!this.deviceManager.isConnected()) {
- await this.deviceManager.connect(next.mode);
- }
- }
- this.currentIndex++;
- current = this.steps[this.currentIndex];
- this.view.onStepStarted(this.currentIndex, current);
- if (!current.needUserGesture) {
- await this.executeStep(current.name);
- }
- }
- }
-
- async executeStep(stepName, loader) {
- const current = this.steps[this.currentIndex];
- let this_command;
- WDebug.log("ControllerManager Execute step", current)
- document.getElementById('error-message-state').style.display = 'none';
- if (current.name === stepName) {
- let res = true;
- let i;
- try {
- for (i= 0; i < current.commands.length && res; i++) {
- this_command = current.commands[i];
- res = await this.runCommand(this_command, loader);
- WDebug.log("run command > ", this_command , "returns ", res);
-
- }
- const next = this.steps[this.currentIndex + 1];
- let previous = this.steps[this.currentIndex - 1];
- if (res) {
- if (next) {
- this.view.onStepFinished(current, next);
- await this.next();
- }
- } else {
- this.view.onStepFailed(current, previous);
- if (!current.needUserGesture) {
- this.currentIndex--;
- }
- throw new Error('command failed');
- }
- } catch (e) {
- throw new Error(`Cannot execute command ${this_command.command}
${e.message || e}`);
- }
- } else {
- throw new Error('this is not the current step ' + current.name + ' is not equals to ' + stepName)
- }
- }
-
- /**
- *
- * @param mode
- * @returns {boolean}
- * Check if device is connected to a mode
- */
- inInMode(mode) {
- return this.deviceManager.isInMode(mode);
- }
-
- /*
- * run a command
- this throw new error if something went wwrong.
- error should contain a proposal to solve the issue.
- */
- async runCommand(cmd, loader) {
- WDebug.log("ControllerManager run command:", cmd);
- switch (cmd.type) {
- case Command.CMD_TYPE.download:
- let res = false;
- try {
- await this.deviceManager.downloadAll((loaded, total, name) => {
- this.view.onDownloading(name, loaded, total);
- }, (loaded, total, name) => {
- this.view.onUnzip(name, loaded, total);
- });
- this.view.onDownloadingEnd();
- return true;
- } catch (e) {
- const proposal = "Proposal: Retry by refreshing this page.";
- throw new Error(`Cannot download
${e.message || e}
${proposal}`);
- }
- return false;
- case Command.CMD_TYPE.reboot:
- try {
- await this.deviceManager.reboot(cmd.mode);
- } catch (e) {
- console.error(e);
- //K1ZFP TODO
- return false;
- }
- return true;
- case Command.CMD_TYPE.connect:
- const proposal = "Proposal: Check connection and that no other program is using the phone and retry.";
- try {
- const res = await this.deviceManager.connect(cmd.mode);
- if (res) {
- await this.onDeviceConnected();
- if(loader) {
- loader.style.display = 'none';
- }
- return true;
- }
- } catch (e) {
- throw new Error(`The device is not connected ${e.message || e}
${proposal}`);
- }
- throw new Error(`Cannot connect the device
${proposal}`);
- case Command.CMD_TYPE.erase:
- return this.deviceManager.erase(cmd.partition);
- case Command.CMD_TYPE.flash:
- return this.deviceManager.flash(cmd.file, cmd.partition, (done, total) => {
- this.view.onInstalling(cmd.file, done, total);
- });
- case Command.CMD_TYPE.unlock:
- //check if unlocked to avoid unnecessary command
- let isUnlocked = false;
- let gotoStep = "";
- if (cmd.partition) {
- try {
- if (cmd.partition.startsWith("goto_")) {
- gotoStep = cmd.partition.substring(5);
- WDebug.log("goto step", gotoStep);
- isUnlocked = await this.deviceManager.getUnlocked('unlocked');
- } else {
- isUnlocked = await this.deviceManager.getUnlocked(cmd.partition);
- }
- } catch (e) {}
- }
- WDebug.log("ControllerManager unlock: ", this.deviceManager.adb.getProductName() + " isUnlocked = " + isUnlocked);
- if (!isUnlocked) {
- try {
- this.deviceManager.unlock(cmd.command); // Do not await thus display unlocking screen
- } catch (e) {
- //on some device, check unlocked does not work but when we try the command, it throws an error with "already unlocked"
- if (e.bootloaderMessage?.includes("already")) {
-
- } else if (e.bootloaderMessage?.includes("not allowed")) {
- //K1ZFP TODO
- }
- }
- } else {
- WDebug.log("The phone is not locked - bypass lock process");
- if (gotoStep=="") { // Goto the next step.
- this.currentIndex++;
- } else { // Goto the maned step.
- do {
- this.currentIndex++;
- WDebug.log("Bypass step", this.steps[this.currentIndex].name + " " + (this.steps[this.currentIndex].name == gotoStep));
- } while ( !(this.steps[this.currentIndex].name == gotoStep) );
- this.currentIndex--;
- }
- }
- return true;
- case Command.CMD_TYPE.lock:
- let isLocked = false;
- if (cmd.partition) {
- try {
- isLocked = !(await this.deviceManager.getUnlocked(cmd.partition));
- } catch (e) {
- }
- }
- if (!isLocked) {
- try {
- this.deviceManager.lock(cmd.command); // Do not await thus display unlocking screen
- } catch (e) {
- //on some device, check unlocked does not work but when we try the command, it throws an error with "already locked"
- if (e.bootloaderMessage?.includes("already")) {
- isLocked = true;
- } else {
- console.error(e); //K1ZFP TODO
- }
- }
- }
- return true;
- case Command.CMD_TYPE.sideload:
- try {
- await this.deviceManager.connect('recovery');
- await this.deviceManager.sideload(cmd.file);
- return true;
- } catch (e) {
- console.error(e); // K1ZFP TODO
- return false;
- }
- case Command.CMD_TYPE.format:
- try {
- this.deviceManager.for(cmd.partition);
- } catch (e) {
- console.error(e); // K1ZFP TODO
- }
- return true;
- case Command.CMD_TYPE.delay:
- await new Promise(resolve => setTimeout(resolve, cmd.partition));
- return true;
-
- default:
- WDebug.log(`try unknown command ${cmd.command}`);
- try {
- await this.deviceManager.runCommand(cmd.command);
- } catch(e) {
- // K1ZFP TODO...
- }
- return true;
- }
- }
-
- async onDeviceConnected() {
-
- const productName = this.deviceManager.getProductName();
- const wasAlreadyConnected = this.deviceManager.wasAlreadyConnected();
- if (!wasAlreadyConnected) {
- this.view.updateData('product-name', productName);
- this.model = productName;
- WDebug.log("ControllerManager Model:", this.model);
- try {
- const resources = await this.getResources();
-
- if(resources.android){
- this.view.updateData('android-version-required', resources.android);
- await this.checkAndroidVersion(resources.android);
- }
- this.setResources(resources);
- } catch(e) {
- this.steps.push(new Step(e.message));
- this.view.updateTotalStep(this.steps.length);
- // Don not throw this error, as it is handled by the UI directly.
- }
- }
- }
- async checkAndroidVersion(versionRequired){
- const android = await this.deviceManager.getAndroidVersion();
- WDebug.log("current android version:", android);
- if( android) {
- this.view.updateData('android-version', android);
- if(android < versionRequired){
- throw Error('android-version-not-supported');
- }
- }
- }
- async getResources(){
-
- let resources = null;
- try {
- let current_security_path_level = null;
- try {
- const security_patch = await this.deviceManager.adb.webusb.getProp("ro.build.version.security_patch");
- //WDebug.log('security_patch', security_patch)
- current_security_path_level = parseInt(security_patch.replace(/-/g, ''), 10);
- WDebug.log("current_security_path_level", current_security_path_level);
-
- } catch(ee) {
- WDebug.log("Security patch Error");
- current_security_path_level = null;
- }
-
- let this_model = this.deviceManager.adb.webusb.device;
- // https://gitlab.e.foundation/e/os/backlog/-/issues/2604#note_609234
- const model = this.deviceManager.adb.webusb.model;
- if (model.includes("Teracube") && model.includes("2e")) {
- try {
- const serial = await this.deviceManager.adb.getSerialNumber();
- WDebug.log("serial numer:", serial);
- if (serial.startsWith("2021")) {
- this_model = "emerald";
- } else if (serial.startsWith("2020")) {
- this_model = "Teracube_2e";
- } else {
- const id =
- "model "+this.deviceManager.adb.webusb.model + " " +
- "product "+this.deviceManager.adb.webusb.product + " " +
- "name "+this.deviceManager.adb.webusb.name + " " +
- "device "+this.deviceManager.adb.webusb.device;
- throw new Error("Cannot find device resource", id);
- }
- } catch (e) {
- const id =
- "model "+this.deviceManager.adb.webusb.model + " " +
- "product "+this.deviceManager.adb.webusb.product + " " +
- "name "+this.deviceManager.adb.webusb.name + " " +
- "device "+this.deviceManager.adb.webusb.device;
- throw new Error("Error on getting devcice resource", id);
- }
-
- }
-
- if (model.includes("A015")) {
- try {
- this_model = "tetris";
- } catch (e) {
- const id =
- "model "+this.deviceManager.adb.webusb.model + " " +
- "product "+this.deviceManager.adb.webusb.product + " " +
- "name "+this.deviceManager.adb.webusb.name + " " +
- "device "+this.deviceManager.adb.webusb.device;
- throw new Error("Error on getting devcice resource", id);
- }
-
- }
-
- resources = await (await fetch(`resources/${this_model}.json`)).json();
- if (current_security_path_level != null && typeof resources.security_patch_level != 'undefined') {
- WDebug.log("EOS Rom has security patch ");
- const new_security_path_level = parseInt(resources.security_patch_level.replace(/-/g, ''), 10);
- if (current_security_path_level > new_security_path_level) {
- WDebug.log("Bypass lock procedure", `resources/${this_model}-safe.json`);
- resources = await (await fetch(`resources/${this_model}-safe.json`)).json();
- }
- }
- } catch (e) {
- resources = null;
- WDebug.log("getRessources Error");
- throw Error('device-model-not-supported');
- }
-
- return resources;
- }
-
- setResources(resources){
- this.resources = resources;
- if (this.resources.steps) {
- this.steps.push(new Step("downloading", 'download', false));
- this.steps.push(...this.resources.steps.map((step) => {
- return new Step(step.id, step.command, step.needUserGesture ?? false, step.mode);
- }));
- this.view.updateTotalStep(this.steps.length);
- }
- this.deviceManager.setResources(this.resources.folder, this.steps);
- }
-}
+import { DeviceManager } from "./controller/device.manager.js";
+import { Command } from "./controller/device/command.class.js";
+import { Step } from "./controller/utils/step.class.js";
+import { WDebug } from "./debug.js";
+/*
+ * Class to manage process
+ * Check and display the steps, interact with deviceManager
+ */
+export class Controller {
+ constructor() {
+ this.steps = [
+ new Step("let-s-get-started", undefined, true),
+ new Step("connect-your-phone", undefined, true),
+ new Step("activate-developer-options", undefined, true),
+ new Step("activate-oem-unlock", undefined, true),
+ new Step("activate-usb-debugging", undefined, true),
+ new Step("enable-usb-file-transfer", undefined, true),
+ new Step("device-detection", "connect adb", true),
+ ];
+ this.currentIndex = 0;
+ }
+
+ async init(view) {
+ this.deviceManager = new DeviceManager();
+ await this.deviceManager.init();
+ this.view = view;
+ }
+
+ async next() {
+ let current = this.steps[this.currentIndex];
+ let next = this.steps[this.currentIndex + 1];
+
+ WDebug.log("Controller Manager Next", next);
+
+ if (next) {
+ //K1ZFP check this
+ if (next.mode) {
+ //if next step require another mode [adb|fastboot|bootloader]
+ if (this.deviceManager.isConnected() && !this.inInMode(next.mode)) {
+ //we need reboot
+ await this.deviceManager.reboot(next.mode);
+ }
+ if (!this.deviceManager.isConnected()) {
+ await this.deviceManager.connect(next.mode);
+ }
+ }
+ this.currentIndex++;
+ current = this.steps[this.currentIndex];
+ this.view.onStepStarted(this.currentIndex, current);
+ if (!current.needUserGesture) {
+ await this.executeStep(current.name);
+ }
+ }
+ }
+
+ async executeStep(stepName, loader) {
+ const current = this.steps[this.currentIndex];
+ let this_command;
+ WDebug.log("ControllerManager Execute step", current);
+ document.getElementById("error-message-state").style.display = "none";
+ if (current.name === stepName) {
+ let res = true;
+ let i;
+ try {
+ for (i = 0; i < current.commands.length && res; i++) {
+ this_command = current.commands[i];
+ res = await this.runCommand(this_command, loader);
+ WDebug.log("run command > ", this_command, "returns ", res);
+ }
+ const next = this.steps[this.currentIndex + 1];
+ let previous = this.steps[this.currentIndex - 1];
+ if (res) {
+ if (next) {
+ this.view.onStepFinished(current, next);
+ await this.next();
+ }
+ } else {
+ this.view.onStepFailed(current, previous);
+ if (!current.needUserGesture) {
+ this.currentIndex--;
+ }
+ throw new Error("command failed");
+ }
+ } catch (e) {
+ throw new Error(
+ `Cannot execute command ${this_command.command}
${e.message || e}`,
+ );
+ }
+ } else {
+ throw new Error(
+ "this is not the current step " +
+ current.name +
+ " is not equals to " +
+ stepName,
+ );
+ }
+ }
+
+ /**
+ *
+ * @param mode
+ * @returns {boolean}
+ * Check if device is connected to a mode
+ */
+ inInMode(mode) {
+ return this.deviceManager.isInMode(mode);
+ }
+
+ /*
+ * run a command
+ this throw new error if something went wwrong.
+ error should contain a proposal to solve the issue.
+ */
+ async runCommand(cmd, loader) {
+ WDebug.log("ControllerManager run command:", cmd);
+ switch (cmd.type) {
+ case Command.CMD_TYPE.download:
+ try {
+ await this.deviceManager.downloadAll(
+ (loaded, total, name) => {
+ this.view.onDownloading(name, loaded, total);
+ },
+ (loaded, total, name) => {
+ this.view.onUnzip(name, loaded, total);
+ },
+ );
+ this.view.onDownloadingEnd();
+ return true;
+ } catch (e) {
+ const proposal = "Proposal: Retry by refreshing this page.";
+ throw new Error(
+ `Cannot download
${e.message || e}
${proposal}`,
+ );
+ }
+ case Command.CMD_TYPE.reboot:
+ try {
+ await this.deviceManager.reboot(cmd.mode);
+ } catch (e) {
+ console.error(e);
+ //K1ZFP TODO
+ return false;
+ }
+ return true;
+ case Command.CMD_TYPE.connect: {
+ const proposal =
+ "Proposal: Check connection and that no other program is using the phone and retry.";
+ try {
+ await this.deviceManager.connect(cmd.mode);
+ await this.onDeviceConnected();
+ if (loader) {
+ loader.style.display = "none";
+ }
+ return true;
+ } catch (e) {
+ throw new Error(
+ `The device is not connected ${e.message || e}
${proposal}`,
+ );
+ }
+ }
+ case Command.CMD_TYPE.erase:
+ return this.deviceManager.erase(cmd.partition);
+ case Command.CMD_TYPE.flash:
+ return this.deviceManager.flash(
+ cmd.file,
+ cmd.partition,
+ (done, total) => {
+ this.view.onInstalling(cmd.file, done, total);
+ },
+ );
+ case Command.CMD_TYPE.unlock: {
+ //check if unlocked to avoid unnecessary command
+ let isUnlocked = false;
+ let gotoStep = "";
+ if (cmd.partition) {
+ if (cmd.partition.startsWith("goto_")) {
+ gotoStep = cmd.partition.substring(5);
+ WDebug.log("goto step", gotoStep);
+ isUnlocked = await this.deviceManager.getUnlocked("unlocked");
+ } else {
+ isUnlocked = await this.deviceManager.getUnlocked(cmd.partition);
+ }
+ }
+ WDebug.log(
+ "ControllerManager unlock: ",
+ this.deviceManager.adb.getProductName() +
+ " isUnlocked = " +
+ isUnlocked,
+ );
+ if (!isUnlocked) {
+ try {
+ this.deviceManager.unlock(cmd.command); // Do not await thus display unlocking screen
+ } catch (e) {
+ //on some device, check unlocked does not work but when we try the command, it throws an error with "already unlocked"
+ if (e.bootloaderMessage?.includes("already")) {
+ WDebug.log("device already unlocked");
+ } else if (e.bootloaderMessage?.includes("not allowed")) {
+ WDebug.log("device unlock is not allowed");
+ }
+ }
+ } else {
+ WDebug.log("The phone is not locked - bypass lock process");
+ if (gotoStep == "") {
+ // Goto the next step.
+ this.currentIndex++;
+ } else {
+ // Goto the maned step.
+ do {
+ this.currentIndex++;
+ WDebug.log(
+ "Bypass step",
+ this.steps[this.currentIndex].name +
+ " " +
+ (this.steps[this.currentIndex].name == gotoStep),
+ );
+ } while (!(this.steps[this.currentIndex].name == gotoStep));
+ this.currentIndex--;
+ }
+ }
+ return true;
+ }
+ case Command.CMD_TYPE.lock: {
+ let isLocked = false;
+ if (cmd.partition) {
+ isLocked = !(await this.deviceManager.getUnlocked(cmd.partition));
+ }
+ if (!isLocked) {
+ try {
+ this.deviceManager.lock(cmd.command); // Do not await thus display unlocking screen
+ } catch (e) {
+ //on some device, check unlocked does not work but when we try the command, it throws an error with "already locked"
+ if (e.bootloaderMessage?.includes("already")) {
+ isLocked = true;
+ } else {
+ console.error(e); //K1ZFP TODO
+ }
+ }
+ }
+ return true;
+ }
+ case Command.CMD_TYPE.sideload:
+ try {
+ await this.deviceManager.connect("recovery");
+ await this.deviceManager.sideload(cmd.file);
+ return true;
+ } catch (e) {
+ console.error(e); // K1ZFP TODO
+ return false;
+ }
+ case Command.CMD_TYPE.format:
+ try {
+ this.deviceManager.for(cmd.partition);
+ } catch (e) {
+ console.error(e); // K1ZFP TODO
+ }
+ return true;
+ case Command.CMD_TYPE.delay:
+ await new Promise((resolve) => setTimeout(resolve, cmd.partition));
+ return true;
+
+ default:
+ WDebug.log(`try unknown command ${cmd.command}`);
+ await this.deviceManager.runCommand(cmd.command);
+ return true;
+ }
+ }
+
+ async onDeviceConnected() {
+ const productName = this.deviceManager.getProductName();
+ const wasAlreadyConnected = this.deviceManager.wasAlreadyConnected();
+ if (!wasAlreadyConnected) {
+ this.view.updateData("product-name", productName);
+ this.model = productName;
+ WDebug.log("ControllerManager Model:", this.model);
+ try {
+ const resources = await this.getResources();
+
+ if (resources.android) {
+ this.view.updateData("android-version-required", resources.android);
+ await this.checkAndroidVersion(resources.android);
+ }
+ this.setResources(resources);
+ } catch (e) {
+ this.steps.push(new Step(e.message));
+ this.view.updateTotalStep(this.steps.length);
+ // Don not throw this error, as it is handled by the UI directly.
+ }
+ }
+ }
+ async checkAndroidVersion(versionRequired) {
+ const android = await this.deviceManager.getAndroidVersion();
+ WDebug.log("current android version:", android);
+ if (android) {
+ this.view.updateData("android-version", android);
+ if (android < versionRequired) {
+ throw Error("android-version-not-supported");
+ }
+ }
+ }
+ async getResources() {
+ let resources = null;
+ try {
+ let current_security_path_level = null;
+ try {
+ const security_patch = await this.deviceManager.adb.webusb.getProp(
+ "ro.build.version.security_patch",
+ );
+ //WDebug.log('security_patch', security_patch)
+ current_security_path_level = parseInt(
+ security_patch.replace(/-/g, ""),
+ 10,
+ );
+ WDebug.log("current_security_path_level", current_security_path_level);
+ } catch {
+ WDebug.log("Security patch Error");
+ current_security_path_level = null;
+ }
+
+ let this_model = this.deviceManager.adb.webusb.device;
+ // https://gitlab.e.foundation/e/os/backlog/-/issues/2604#note_609234
+ const model = this.deviceManager.adb.webusb.model;
+ if (model.includes("Teracube") && model.includes("2e")) {
+ try {
+ const serial = await this.deviceManager.adb.getSerialNumber();
+ WDebug.log("serial numer:", serial);
+ if (serial.startsWith("2021")) {
+ this_model = "emerald";
+ } else if (serial.startsWith("2020")) {
+ this_model = "Teracube_2e";
+ } else {
+ const id =
+ "model " +
+ this.deviceManager.adb.webusb.model +
+ " " +
+ "product " +
+ this.deviceManager.adb.webusb.product +
+ " " +
+ "name " +
+ this.deviceManager.adb.webusb.name +
+ " " +
+ "device " +
+ this.deviceManager.adb.webusb.device;
+ throw new Error("Cannot find device resource", id);
+ }
+ } catch {
+ const id =
+ "model " +
+ this.deviceManager.adb.webusb.model +
+ " " +
+ "product " +
+ this.deviceManager.adb.webusb.product +
+ " " +
+ "name " +
+ this.deviceManager.adb.webusb.name +
+ " " +
+ "device " +
+ this.deviceManager.adb.webusb.device;
+ throw new Error("Error on getting device resource", id);
+ }
+ }
+
+ if (model.includes("A015")) {
+ try {
+ this_model = "tetris";
+ } catch {
+ const id =
+ "model " +
+ this.deviceManager.adb.webusb.model +
+ " " +
+ "product " +
+ this.deviceManager.adb.webusb.product +
+ " " +
+ "name " +
+ this.deviceManager.adb.webusb.name +
+ " " +
+ "device " +
+ this.deviceManager.adb.webusb.device;
+ throw new Error("Error on getting devcice resource", id);
+ }
+ }
+
+ resources = await (await fetch(`resources/${this_model}.json`)).json();
+ if (
+ current_security_path_level != null &&
+ typeof resources.security_patch_level != "undefined"
+ ) {
+ WDebug.log("EOS Rom has security patch ");
+ const new_security_path_level = parseInt(
+ resources.security_patch_level.replace(/-/g, ""),
+ 10,
+ );
+ if (current_security_path_level > new_security_path_level) {
+ WDebug.log(
+ "Bypass lock procedure",
+ `resources/${this_model}-safe.json`,
+ );
+ resources = await (
+ await fetch(`resources/${this_model}-safe.json`)
+ ).json();
+ }
+ }
+ } catch (e) {
+ resources = null;
+ WDebug.log("getResources Error: " + e);
+ throw Error("device-model-not-supported");
+ }
+
+ return resources;
+ }
+
+ setResources(resources) {
+ this.resources = resources;
+ if (this.resources.steps) {
+ this.steps.push(new Step("downloading", "download", false));
+ this.steps.push(
+ ...this.resources.steps.map((step) => {
+ return new Step(
+ step.id,
+ step.command,
+ step.needUserGesture ?? false,
+ step.mode,
+ );
+ }),
+ );
+ this.view.updateTotalStep(this.steps.length);
+ }
+ this.deviceManager.setResources(this.resources.folder, this.steps);
+ }
+}
diff --git a/app/src/controller/device.manager.js b/app/src/controller/device.manager.js
index bf600b1b2458625c67ea0c410bd432f5e353ee87..981d2c6865dd05dbad8ec5eaf587ea34fade8eae 100644
--- a/app/src/controller/device.manager.js
+++ b/app/src/controller/device.manager.js
@@ -1,199 +1,200 @@
-import {Bootloader} from "./device/bootloader.class.js";
-import {Downloader} from "./downloader.manager.js";
-import {ADB} from "./device/adb.class.js";
-import {Recovery} from "./device/recovery.class.js";
-import {Device} from "./device/device.class.js";
-const MODE = {
- adb: 'adb',
- recovery: 'recovery',
- bootloader: 'bootloader',
-}
-
-/**
- * wrap device functions
- * */
-export class DeviceManager {
- constructor() {
- this.model = '';
- this.rom = undefined;
- this.key = undefined;
- this.patch = [];
- this.oem = undefined;
- this.device = new Device();
- this.bootloader = new Bootloader();
- this.recovery = new Recovery();
- this.adb = new ADB();
- this.downloader = new Downloader();
- this.wasConnected = false;
- }
-
- async init() {
- await this.bootloader.init();
- await this.adb.init();
- await this.recovery.init();
- await this.downloader.init();
- }
-
-
- wasAlreadyConnected() {
- if (this.wasConnected == false) {
- this.wasConnected = true;
- return false;
- }
- return true;
- }
-
- setResources(folder, steps ) {
- this.folder = folder;
- this.files = steps.map(s => {
- return s.commands.map(c => {
- return c.file;
- })
- }).flat();
- }
-
- async getUnlocked(variable) {
- return this.bootloader.isUnlocked(variable);
- }
- async getAndroidVersion() {
- return await this.device.getAndroidVersion();
- }
- async isDetected(){
- const serial = this.serialNumber;
- if(serial) {
- const devices = await navigator.usb.getDevices();
- return !!devices.length;
- }
- return false;
- }
-
-
- /**
- * @param mode
- * @returns {any}
- *
- * We set the device to the mode manager we went to connect to
- * And we connect the device
- *
- */
- async setMode(mode) {
- switch (mode) {
- case MODE.bootloader :
- this.device = this.bootloader;
- break;
- case MODE.adb :
- this.device = this.adb;
- break;
- case MODE.recovery :
- this.device = this.recovery;
- break;
- }
- }
- async connect(mode) {
- await this.setMode(mode);
- try {
- return await this.device.connect();
- } catch(e) {
- throw new Error(`Failed to connect: ${e.message || e}`);
- }
- }
-
- isConnected() {
- return this.device.isConnected();
- }
- /**
- * @param mode
- * @returns {boolean}
- *
- */
- isInMode(mode) {
- if(this.isConnected()){
- switch (mode) {
- case 'bootloader':
- return this.device.isBootloader();
- case 'adb':
- return this.device.isADB();
- case 'recovery':
- return this.device.isRecovery();
- }
- }
- return false;
- }
-
- erase(partition) {
- return this.bootloader.runCommand(`erase:${partition}`);
- }
-
- format(argument) {
- return true;
-// return this.bootloader.runCommand(`format ${argument}`);
-// the fastboot format md_udc is not supported evne by the official fastboot program
- }
-
- unlock(command) {
- return this.bootloader.runCommand(command);
- }
-
- lock(command) {
- return this.bootloader.runCommand(command);
- }
-
- async flash(file, partition, onProgress) {
- let blob = await this.downloader.getFile(file);
- if (!blob) {
- throw new Error(`error getting blob file ${file}`);
- }
- let flashed = false;
- try {
- flashed = await this.bootloader.flashBlob(partition, blob, onProgress);
- }
- catch (e) {
- throw new Error(`error flashing file ${file} ${e.message || e}`);
- }
- return flashed;
- }
-
-
- getProductName() {
- return this.device.getProductName();
- }
-
- getSerialNumber() {
- return this.device.getSerialNumber();
- }
-
-
-
- async reboot(mode) {
- const res = await this.device.reboot(mode);
- if(res) {
- this.setMode(mode);
- }
- return res;
- }
-
- async sideload(file) {
- let blob = await this.downloader.getFile(file);
- if (!blob) {
- throw new Error(`error getting blob file ${file}`);
- }
-
- return await this.device.sideload(blob);
- }
-
- async runCommand(command) {
- try {
- return this.device.runCommand(command);
- } catch (e) {
- throw new Error(`error ${command} failed
${e.message || e}`);
- }
- }
-
- async downloadAll(onProgress, onUnzip) {
- try {
- await this.downloader.downloadAndUnzipFolder(this.files, this.folder, onProgress, onUnzip);
- } catch (e) {
- throw new Error(`downloadAll error ${e.message || e}`);
- }
- }
-}
\ No newline at end of file
+import { Bootloader } from "./device/bootloader.class.js";
+import { Downloader } from "./downloader.manager.js";
+import { ADB } from "./device/adb.class.js";
+import { Recovery } from "./device/recovery.class.js";
+import { Device } from "./device/device.class.js";
+const MODE = {
+ adb: "adb",
+ recovery: "recovery",
+ bootloader: "bootloader",
+};
+
+/**
+ * wrap device functions
+ * */
+export class DeviceManager {
+ constructor() {
+ this.model = "";
+ this.rom = undefined;
+ this.key = undefined;
+ this.patch = [];
+ this.oem = undefined;
+ this.device = new Device();
+ this.bootloader = new Bootloader();
+ this.recovery = new Recovery();
+ this.adb = new ADB();
+ this.downloader = new Downloader();
+ this.wasConnected = false;
+ }
+
+ async init() {
+ await this.bootloader.init();
+ await this.adb.init();
+ await this.recovery.init();
+ await this.downloader.init();
+ }
+
+ wasAlreadyConnected() {
+ if (this.wasConnected == false) {
+ this.wasConnected = true;
+ return false;
+ }
+ return true;
+ }
+
+ setResources(folder, steps) {
+ this.folder = folder;
+ this.files = steps
+ .map((s) => {
+ return s.commands.map((c) => {
+ return c.file;
+ });
+ })
+ .flat();
+ }
+
+ async getUnlocked(variable) {
+ return this.bootloader.isUnlocked(variable);
+ }
+ async getAndroidVersion() {
+ return await this.device.getAndroidVersion();
+ }
+ async isDetected() {
+ const serial = this.serialNumber;
+ if (serial) {
+ const devices = await navigator.usb.getDevices();
+ return !!devices.length;
+ }
+ return false;
+ }
+
+ /**
+ * @param mode
+ * @returns {any}
+ *
+ * We set the device to the mode manager we went to connect to
+ * And we connect the device
+ *
+ */
+ async setMode(mode) {
+ switch (mode) {
+ case MODE.bootloader:
+ this.device = this.bootloader;
+ break;
+ case MODE.adb:
+ this.device = this.adb;
+ break;
+ case MODE.recovery:
+ this.device = this.recovery;
+ break;
+ }
+ }
+ async connect(mode) {
+ await this.setMode(mode);
+ try {
+ return await this.device.connect();
+ } catch (e) {
+ throw new Error(`Failed to connect: ${e.message || e}`);
+ }
+ }
+
+ isConnected() {
+ return this.device.isConnected();
+ }
+ /**
+ * @param mode
+ * @returns {boolean}
+ *
+ */
+ isInMode(mode) {
+ if (this.isConnected()) {
+ switch (mode) {
+ case "bootloader":
+ return this.device.isBootloader();
+ case "adb":
+ return this.device.isADB();
+ case "recovery":
+ return this.device.isRecovery();
+ }
+ }
+ return false;
+ }
+
+ erase(partition) {
+ return this.bootloader.runCommand(`erase:${partition}`);
+ }
+
+ format() {
+ return true;
+ // return this.bootloader.runCommand(`format ${argument}`);
+ // the fastboot format md_udc is not supported evne by the official fastboot program
+ }
+
+ unlock(command) {
+ return this.bootloader.runCommand(command);
+ }
+
+ lock(command) {
+ return this.bootloader.runCommand(command);
+ }
+
+ async flash(file, partition, onProgress) {
+ let blob = await this.downloader.getFile(file);
+ if (!blob) {
+ throw new Error(`error getting blob file ${file}`);
+ }
+ let flashed = false;
+ try {
+ flashed = await this.bootloader.flashBlob(partition, blob, onProgress);
+ } catch (e) {
+ throw new Error(`error flashing file ${file} ${e.message || e}`);
+ }
+ return flashed;
+ }
+
+ getProductName() {
+ return this.device.getProductName();
+ }
+
+ getSerialNumber() {
+ return this.device.getSerialNumber();
+ }
+
+ async reboot(mode) {
+ const res = await this.device.reboot(mode);
+ if (res) {
+ this.setMode(mode);
+ }
+ return res;
+ }
+
+ async sideload(file) {
+ let blob = await this.downloader.getFile(file);
+ if (!blob) {
+ throw new Error(`error getting blob file ${file}`);
+ }
+
+ return await this.device.sideload(blob);
+ }
+
+ async runCommand(command) {
+ try {
+ return this.device.runCommand(command);
+ } catch (e) {
+ throw new Error(`error ${command} failed
${e.message || e}`);
+ }
+ }
+
+ async downloadAll(onProgress, onUnzip) {
+ try {
+ await this.downloader.downloadAndUnzipFolder(
+ this.files,
+ this.folder,
+ onProgress,
+ onUnzip,
+ );
+ } catch (e) {
+ throw new Error(`downloadAll error ${e.message || e}`);
+ }
+ }
+}
diff --git a/app/src/controller/device/adb.class.js b/app/src/controller/device/adb.class.js
index 28adebcd9e28356d2a98ae75258d82b3c91c9c41..86bd536d4e2c6e94e97e4e4487bfb963dd1b1379 100644
--- a/app/src/controller/device/adb.class.js
+++ b/app/src/controller/device/adb.class.js
@@ -1,79 +1,70 @@
-import {Device} from "./device.class.js";
-import {WDebug} from "../../debug.js";
-import {AdbWebBackend, Adb2} from "../../lib/webadb/adb.bundle.js";
-
-export class ADB extends Device {
- constructor(device) {
- super(device);
- this.webusb = null;
- }
-
- async isConnected() {
- if (!this.device) {
- return false;
- }
- try {
- return this.device.getDevice();
- } catch (e) {
- return false;
- }
- }
-
- isADB() {
- return true;
- }
-
- async connect(cb) {
- let res = false;
- try {
- console.log("debug adb connect")
- let adbWebBackend = await AdbWebBackend.requestDevice();
- if (adbWebBackend) {
- let adbDevice = new Adb2(adbWebBackend, null); //adb.bundle.js
- await adbDevice.connect();
- this.device = adbWebBackend._device;
- this.webusb = adbDevice;
-
- WDebug.log("----------------------------------");
- WDebug.log("Model", adbDevice.model);
- WDebug.log("product", adbDevice.product);
- WDebug.log("Name", adbDevice.name);
- WDebug.log(">Device (codename)", adbDevice.device); // codemane
- WDebug.log("----------------------------------");
-
- res = true;
- }
- } catch (e) {
- this.device = null;
- throw new Error(`Cannot connect ADB ${e.message || e}`);
- } finally {
- return res;
- }
- }
-
- getProductName() {
- return this.webusb.name;
- }
-
- async getAndroidVersion() {
- return this.webusb.getProp('ro.build.version.release');
- }
-
- async getSerialNumber() {
- return this.webusb.getProp("ro.boot.serialno");
- }
-
- async runCommand(cmd) {
- WDebug.log("ADB Run command>", cmd);
- return await this.webusb.exec(cmd);
- }
-
- async reboot(mode) {
- const res = await this.webusb.createStreamAndReadAll(`reboot:${mode}`);
- return res;
-
- }
-
-
-
-}
+import { Device } from "./device.class.js";
+import { WDebug } from "../../debug.js";
+import { AdbWebBackend, Adb2 } from "../../lib/webadb/adb.bundle.js";
+
+export class ADB extends Device {
+ constructor(device) {
+ super(device);
+ this.webusb = null;
+ }
+
+ async isConnected() {
+ if (!this.device) {
+ return false;
+ }
+ try {
+ return this.device.getDevice();
+ } catch {
+ return false;
+ }
+ }
+
+ isADB() {
+ return true;
+ }
+
+ async connect() {
+ try {
+ console.log("debug adb connect");
+ let adbWebBackend = await AdbWebBackend.requestDevice();
+ if (adbWebBackend) {
+ let adbDevice = new Adb2(adbWebBackend, null); //adb.bundle.js
+ await adbDevice.connect();
+ this.device = adbWebBackend._device;
+ this.webusb = adbDevice;
+
+ WDebug.log("----------------------------------");
+ WDebug.log("Model", adbDevice.model);
+ WDebug.log("product", adbDevice.product);
+ WDebug.log("Name", adbDevice.name);
+ WDebug.log(">Device (codename)", adbDevice.device); // codemane
+ WDebug.log("----------------------------------");
+ }
+ } catch (e) {
+ this.device = null;
+ throw new Error(`Cannot connect ADB ${e.message || e}`);
+ }
+ }
+
+ getProductName() {
+ return this.webusb.name;
+ }
+
+ async getAndroidVersion() {
+ return this.webusb.getProp("ro.build.version.release");
+ }
+
+ async getSerialNumber() {
+ return this.webusb.getProp("ro.boot.serialno");
+ }
+
+ async runCommand(cmd) {
+ WDebug.log("ADB Run command>", cmd);
+ return await this.webusb.exec(cmd);
+ }
+
+ async reboot(mode) {
+ const res = await this.webusb.createStreamAndReadAll(`reboot:${mode}`);
+ return res;
+ }
+}
diff --git a/app/src/controller/device/bootloader.class.js b/app/src/controller/device/bootloader.class.js
index 8e9e48a21a82c6e704d867f3751723056381ffce..86df50c2869f37e59b3d0a77524cca7734605807 100644
--- a/app/src/controller/device/bootloader.class.js
+++ b/app/src/controller/device/bootloader.class.js
@@ -1,153 +1,134 @@
-import * as fastboot from "../../lib/fastboot/fastboot.js";
-import {TimeoutError} from "../../lib/fastboot/fastboot.js";
-import {Device} from "./device.class.js";
-import { WDebug } from "../../debug.js";
-
-/**
- * wrap fastboot interactions
- * */
-export class Bootloader extends Device {
-
- constructor() {
- super(new fastboot.FastbootDevice());
- }
-
- async init() {
- //await this.blobStore.init();
- fastboot.configureZip({
- workerScripts: {
- inflate: ["../dist/vendor/z-worker-pako.js", "pako_inflate.min.js"],
- },
- });
- // Enable verbose debug logging
- fastboot.setDebugLevel(2);
- }
-
- reboot(mode) {
- return this.device.reboot(mode);
- }
-
- runCommand(command) {
- return this.device.runCommand(command);
- }
-
- isConnected() {
- return this.device.isConnected;
- }
-
- isBootloader() {
- return true;
- }
-
- async connect() {
- let connected = false;
- try {
- await this.device.connect();
- connected = true;
- } catch (e) {
- throw new Error("Cannot connect Bootloader", `${e.message || e}`);
- } finally {
- return connected;
- }
- }
-
- getProductName() {
- return this.device.device.productName;
- }
-
- getSerialNumber() {
- return this.device.device.serialNumber;
- }
-
- async flashFactoryZip(blob, onProgress, onReconnect) {
- try {
- await this.device.flashFactoryZip(
- blob,
- false,
- onReconnect,
- // Progress callback
- (action, item, progress) => {
- let userAction = fastboot.USER_ACTION_MAP[action];
- onProgress(userAction, item, progress);
- }
- );
- } catch (e) {
- throw e;
- }
- }
-
- async flashBlob(partition, blob, onProgress) {
- try {
- await this.device.flashBlob(
- partition,
- blob,
- (progress) => {
- onProgress(progress * blob.size, blob.size, partition);
- }
- );
- onProgress(blob.size, blob.size, partition);
- return true;
- } catch (e) {
- if (e instanceof TimeoutError) {
- WDebug.log("Timeout on flashblob >" + partition);
- return await this.flashBlob(partition, blob, onProgress);
- } else {
- console.log("flashBlob error", e);
- throw new Error(`Bootloader error: ${e.message || e}`);
- }
- }
- }
-
- bootBlob(blob) {
- return this.device.bootBlob(blob);
- }
-
- async isUnlocked(variable) {
- if (this.device && this.device.isConnected) {
- try {
- const unlocked = await this.device.getVariable(variable);
- return !(!unlocked || unlocked === 'no');
- } catch (e) {
- console.error(e); // K1ZFP TODO
- throw e;
- }
- }
- return false;
- }
-
- async isLocked(variable) {
- if (this.device && this.device.isConnected) {
- try {
- const unlocked = await this.device.getVariable(variable);
- return !unlocked || unlocked === 'no';
- } catch (e) {
- console.error(e); //K1ZFP TODO
- throw e;
- }
- }
- return false;
- }
-
- async unlock(command) {
- if (command) {
- const res = await this.device.runCommand(command);
- } else {
- throw Error('no unlock command configured'); //K1ZFP TODO
- }
- }
-
- async lock(command) {
- if (command) {
- try {
- const res = await this.device.runCommand(command);
- return !(await this.isUnlocked());
- } catch (e) {
- throw e;
- }
- } else {
- throw Error('no lock command configured'); //K1ZFP TODO
- }
- }
-
-
-}
\ No newline at end of file
+import * as fastboot from "../../lib/fastboot/fastboot.js";
+import { TimeoutError } from "../../lib/fastboot/fastboot.js";
+import { Device } from "./device.class.js";
+import { WDebug } from "../../debug.js";
+
+/**
+ * wrap fastboot interactions
+ * */
+export class Bootloader extends Device {
+ constructor() {
+ super(new fastboot.FastbootDevice());
+ }
+
+ async init() {
+ //await this.blobStore.init();
+ fastboot.configureZip({
+ workerScripts: {
+ inflate: ["../dist/vendor/z-worker-pako.js", "pako_inflate.min.js"],
+ },
+ });
+ // Enable verbose debug logging
+ fastboot.setDebugLevel(2);
+ }
+
+ reboot(mode) {
+ return this.device.reboot(mode);
+ }
+
+ runCommand(command) {
+ return this.device.runCommand(command);
+ }
+
+ isConnected() {
+ return this.device.isConnected;
+ }
+
+ isBootloader() {
+ return true;
+ }
+
+ async connect() {
+ try {
+ await this.device.connect();
+ } catch (e) {
+ throw new Error("Cannot connect Bootloader", `${e.message || e}`);
+ }
+ }
+
+ getProductName() {
+ return this.device.device.productName;
+ }
+
+ getSerialNumber() {
+ return this.device.device.serialNumber;
+ }
+
+ async flashFactoryZip(blob, onProgress, onReconnect) {
+ await this.device.flashFactoryZip(
+ blob,
+ false,
+ onReconnect,
+ // Progress callback
+ (action, item, progress) => {
+ let userAction = fastboot.USER_ACTION_MAP[action];
+ onProgress(userAction, item, progress);
+ },
+ );
+ }
+
+ async flashBlob(partition, blob, onProgress) {
+ try {
+ await this.device.flashBlob(partition, blob, (progress) => {
+ onProgress(progress * blob.size, blob.size, partition);
+ });
+ onProgress(blob.size, blob.size, partition);
+ return true;
+ } catch (e) {
+ if (e instanceof TimeoutError) {
+ WDebug.log("Timeout on flashblob >" + partition);
+ return await this.flashBlob(partition, blob, onProgress);
+ } else {
+ console.log("flashBlob error", e);
+ throw new Error(`Bootloader error: ${e.message || e}`);
+ }
+ }
+ }
+
+ bootBlob(blob) {
+ return this.device.bootBlob(blob);
+ }
+
+ async isUnlocked(variable) {
+ if (this.device && this.device.isConnected) {
+ try {
+ const unlocked = await this.device.getVariable(variable);
+ return !(!unlocked || unlocked === "no");
+ } catch (e) {
+ console.error(e); // K1ZFP TODO
+ throw e;
+ }
+ }
+ return false;
+ }
+
+ async isLocked(variable) {
+ if (this.device && this.device.isConnected) {
+ try {
+ const unlocked = await this.device.getVariable(variable);
+ return !unlocked || unlocked === "no";
+ } catch (e) {
+ console.error(e); //K1ZFP TODO
+ throw e;
+ }
+ }
+ return false;
+ }
+
+ async unlock(command) {
+ if (command) {
+ await this.device.runCommand(command);
+ } else {
+ throw Error("no unlock command configured"); //K1ZFP TODO
+ }
+ }
+
+ async lock(command) {
+ if (command) {
+ await this.device.runCommand(command);
+ return !(await this.isUnlocked());
+ } else {
+ throw Error("no lock command configured"); //K1ZFP TODO
+ }
+ }
+}
diff --git a/app/src/controller/device/command.class.js b/app/src/controller/device/command.class.js
index 5faf6c3c2e5363158e81abd1111c48bbda5825ea..b572d2df9caf6be8fec19da68fb4746d1ba4fbdd 100644
--- a/app/src/controller/device/command.class.js
+++ b/app/src/controller/device/command.class.js
@@ -1,74 +1,77 @@
-import { WDebug } from "../../debug.js";
-
-export class Command {
- static CMD_TYPE = {
- flash: 'flash',
- sideload: 'sideload',
- erase: 'erase',
- unlock: 'unlock',
- lock: 'lock',
- connect: 'connect',
- reboot: 'reboot',
- download: 'download',
- format: 'format',
- delay: 'delay'
- };
-
- constructor(cmd) {
- this.command = cmd;
- this.type = undefined;
- this.mode = undefined;
- this.partition = undefined;
- this.file = undefined;
- this.parseCommand(cmd);
- }
-
- parseCommand(cmd) {
- const res = cmd.split(' ').map(m => m.trim()).filter(m => m != '');
- WDebug.log(`command.class parseCommand : ${cmd}`);
- switch (res[0]) {
- case 'download':
- this.type = Command.CMD_TYPE.download;
- break
- case 'connect':
- this.type = Command.CMD_TYPE.connect;
- this.mode = res[1]; // adb or fastboot;
- break
- case 'flash':
- this.type = Command.CMD_TYPE.flash;
- this.partition = res[1];
- this.file = res[2];
- break;
- case 'sideload':
- this.type = Command.CMD_TYPE.sideload;
- this.file = res[1];
- break;
- case 'erase':
- this.type = Command.CMD_TYPE.erase;
- this.partition = res[1];
- break;
- case 'reboot':
- this.type = Command.CMD_TYPE.reboot;
- this.mode = res[1];
- break;
- case 'flashing':
- case 'oem':
- this.command = `${res[0]} ${res[1]}`;
- this.partition = res[2];
- if (res[1].startsWith('unlock')) {
- this.type = Command.CMD_TYPE.unlock;
- } else if (res[1].startsWith('lock')) {
- this.type = Command.CMD_TYPE.lock;
- }
- break;
- case 'delay' :
- this.type = Command.CMD_TYPE.delay;
- this.partition = parseInt(res[1], 10)*1000;
- break;
- case 'format':
- this.partition = res[1];
- this.type = Command.CMD_TYPE.format;
- break;
- }
- }
-}
\ No newline at end of file
+import { WDebug } from "../../debug.js";
+
+export class Command {
+ static CMD_TYPE = {
+ flash: "flash",
+ sideload: "sideload",
+ erase: "erase",
+ unlock: "unlock",
+ lock: "lock",
+ connect: "connect",
+ reboot: "reboot",
+ download: "download",
+ format: "format",
+ delay: "delay",
+ };
+
+ constructor(cmd) {
+ this.command = cmd;
+ this.type = undefined;
+ this.mode = undefined;
+ this.partition = undefined;
+ this.file = undefined;
+ this.parseCommand(cmd);
+ }
+
+ parseCommand(cmd) {
+ const res = cmd
+ .split(" ")
+ .map((m) => m.trim())
+ .filter((m) => m != "");
+ WDebug.log(`command.class parseCommand : ${cmd}`);
+ switch (res[0]) {
+ case "download":
+ this.type = Command.CMD_TYPE.download;
+ break;
+ case "connect":
+ this.type = Command.CMD_TYPE.connect;
+ this.mode = res[1]; // adb or fastboot;
+ break;
+ case "flash":
+ this.type = Command.CMD_TYPE.flash;
+ this.partition = res[1];
+ this.file = res[2];
+ break;
+ case "sideload":
+ this.type = Command.CMD_TYPE.sideload;
+ this.file = res[1];
+ break;
+ case "erase":
+ this.type = Command.CMD_TYPE.erase;
+ this.partition = res[1];
+ break;
+ case "reboot":
+ this.type = Command.CMD_TYPE.reboot;
+ this.mode = res[1];
+ break;
+ case "flashing":
+ case "oem":
+ this.command = `${res[0]} ${res[1]}`;
+ this.partition = res[2];
+ if (res[1].startsWith("unlock")) {
+ this.type = Command.CMD_TYPE.unlock;
+ } else if (res[1].startsWith("lock")) {
+ this.type = Command.CMD_TYPE.lock;
+ }
+ break;
+ case "delay":
+ this.type = Command.CMD_TYPE.delay;
+ this.partition = parseInt(res[1], 10) * 1000;
+ break;
+ case "format":
+ this.partition = res[1];
+ this.type = Command.CMD_TYPE.format;
+ break;
+ }
+ }
+}
diff --git a/app/src/controller/device/device.class.js b/app/src/controller/device/device.class.js
index ee68e8b91e09c0619b885569101728c823b0a88d..10bcdb9882dd7e4de92809440db167f9f4fdb40b 100644
--- a/app/src/controller/device/device.class.js
+++ b/app/src/controller/device/device.class.js
@@ -1,60 +1,56 @@
-export class Device {
- constructor(device) {
- this.device = device;
- }
-
- async init() {
-
- }
-
- async connect() {
- return false;
- }
-
- isConnected() {
- return false;
- }
-
- isADB() {
- return false;
- }
-
- isBootloader() {
- return false;
- }
-
- isFastboot() {
- return false;
- }
-
- isRecovery() {
- return false;
- }
-
- async flashBlob(partition, blob, onProgress) {
- return false;
- }
-
- async runCommand(cmd) {
- return false;
- }
-
- getProductName() {
- return undefined;
- }
-
- getSerialNumber() {
- return undefined;
- }
- async getAndroidVersion() {
- return undefined;
- }
-
- reboot(mode) {
- return undefined;
- }
-
- async bootBlob(blob) {
- return false;
- }
-}
\ No newline at end of file
+export class Device {
+ constructor(device) {
+ this.device = device;
+ }
+
+ async init() {}
+
+ async connect() {}
+
+ isConnected() {
+ return false;
+ }
+
+ isADB() {
+ return false;
+ }
+
+ isBootloader() {
+ return false;
+ }
+
+ isFastboot() {
+ return false;
+ }
+
+ isRecovery() {
+ return false;
+ }
+
+ async flashBlob() {
+ return false;
+ }
+
+ async runCommand() {
+ return false;
+ }
+
+ getProductName() {
+ return undefined;
+ }
+
+ getSerialNumber() {
+ return undefined;
+ }
+ async getAndroidVersion() {
+ return undefined;
+ }
+
+ reboot() {
+ return undefined;
+ }
+
+ async bootBlob() {
+ return false;
+ }
+}
diff --git a/app/src/controller/device/recovery.class.js b/app/src/controller/device/recovery.class.js
index 3114594770f59d51cc500de1c5c1fa5b88fc34ed..d786ba178194729103cf1cf5d5d1f6d134d8bee4 100644
--- a/app/src/controller/device/recovery.class.js
+++ b/app/src/controller/device/recovery.class.js
@@ -1,432 +1,158 @@
-import {MessageClass} from "../../lib/webadb/message.class.js";
-import {MessageHeader} from "../../lib/webadb/message-header.class.js";
-import {Device} from "./device.class.js";
-import {WDebug} from "../../debug.js";
-import {AdbWebBackend3, Adb3} from "../../lib/webadb/adb.bundle.js";
-
-export class Recovery extends Device {
- constructor(device) {
- super(device);
- this.webusb = null;
- this.count = 0;
- this.adbWebBackend = null;
- }
-
- async isConnected() {
- if (!this.device) {
- return false;
- }
- try {
- return this.device.getDevice();
- } catch (e) {
- return false;
- }
- }
-
- isRecovery() {
- return true;
- }
-
- async connect() {
- let res = false;
- try {
- if (this.device && this.device.isConnected) {
- WDebug.log("Connect recovery the device is connected");
- } else {
- const adbWebBackend = await AdbWebBackend3.requestDevice();
- WDebug.log("adbWebBackend = ", adbWebBackend);
- const adbDevice = new Adb3(adbWebBackend, null); //adb.bundle.js
- WDebug.log("adbDevice = ", adbDevice);
- await adbDevice.connect();
- WDebug.log("adbDevice connected");
- this.device = adbWebBackend._device;
- this.webusb = adbDevice;
- this.adbWebBackend = adbWebBackend;
- res = true;
- }
- return true;
- } catch (e) {
- this.device = null;
- throw new Error(`Cannot connect Recovery ${e.message || e}`);
- } finally {
- return res;
- }
- }
-
- async sideload(blob, onProgress) {
- let res = false;
- try {
- await this.adbOpen(blob, true);
- res = true;
- } catch (e) {
- throw new Error(`Sideload fails ${e.message || e}`);
- } finally {
- return res;
- }
- }
-
- async reboot(mode) {
- return await this.device.shell(`reboot ${mode}`);
- }
-
- getProductName() {
- return this.webusb.name;
- }
-
- getSerialNumber() {
- return this.webusb.product;
- }
-
- async _______adbOpen_DEPRECATED(blob, useChecksum ) {
-// K1ZFP this one is used by the webadb.js lib that does not works on MacOS
- const transport = this.device.transport;
- if (transport == null)
- return;
-
- const encoder = new TextEncoder();
- const decoder = new TextDecoder();
-
- const MAX_PAYLOAD = this.device.max_payload;
- const fileSize = blob.size;
- const service = `sideload-host:${fileSize}:${MAX_PAYLOAD}`; //sideload-host:1381604186:262144
-
- let data = new DataView(encoder.encode('' + service + '\0').buffer);
- this.stream = await Adb.Stream.open(this.device, service); // Send OPEN message and receive OKAY
-
- let checksum = 0;
- if (useChecksum) {
- checksum = MessageClass.checksum(data);
- }
- const localId = this.stream.local_id;
- const remoteId = this.stream.remote_id;
-
-
- let header = new MessageHeader('OKAY', localId, remoteId, 0, checksum);
- let receivedData;
- const hh = header.toDataView().buffer
- /*
- Index Valeur (Int8)
- 0 79
- 1 75
- 2 65
- 3 89
- 4 1
- 5 0
- 6 0
- 7 0
- 8 1
- 9 0
- 10 0
- 11 0
- 12 0
- 13 0
- 14 0
- 15 0
- 16 -35
- 17 8
- 18 0
- 19 0
- 20 -80
- 21 -76
- 22 -66
- 23 -90
- */
- await this.write(hh);
-
- let response_h = await this.read(24);
- /*
- Index Valeur (Int8) Interprétation ASCII
- 0 87 W
- 1 82 R
- 2 84 T
- 3 69 E
- 4 1
- 5 0
- 6 0
- 7 0
- 8 1
- 9 0
- 10 0
- 11 0
- 12 8
- 13 0
- 14 0
- 15 0
- 16 -114
- 17 1
- 18 0
- 19 0
- 20 -88
- 21 -83
- 22 -85
- 23 -70
- */
-
- header = MessageHeader.parse(response_h, useChecksum);
- switch (header.cmd) {
- default: {
- if (header.length > 0) { //=8
- receivedData = await this.read(header.length); //READ...
- /*
- Int8Array(8)
- 0 : 48
- 1 : 48
- 2 : 48
- 3 : 48
- 4 : 53
- 5 : 50
- 6 : 55
- 7 : 48
- */
- }
- }
- }
-
- let message = new MessageClass(header, receivedData);
- if (message.header.cmd !== 'WRTE') {
- throw new Error('WRTE Failed');
- }
-
- while (true) {
- let res = decoder.decode(message.data); //1pass 1 2pass 0 // 5270
- const block = Number(res);
-
- if (isNaN(block) && res === 'DONEDONE') {
- break;
- }
-
- const offset = block * MAX_PAYLOAD; //1381498880
- if (offset >= fileSize) { //1381604186
- throw new Error(`adb: failed to read block ${block} past end`);
- }
-
- let to_write = MAX_PAYLOAD; //105306
- if ((offset + MAX_PAYLOAD) > fileSize) {
- to_write = fileSize - offset;
- }
-
- const slice = blob.slice(offset, offset + to_write); //K1ZFP type?
- //cons ole.log("offset to_write", offset, to_write); // 1 179 254 784
- //cons ole.log("to_write(" + to_write + ") offset(" + offset + ") " + (await slice.arrayBuffer()).byteLength);
-
- let header = new MessageHeader('WRTE', localId, remoteId, to_write, checksum);
- let hhh = header.toDataView().buffer;
- /*
- 0 87 W
- 1 82 R
- 2 84 T
- 3 69 E
- 4 1
- 5 0
- 6 0
- 7 0
- 8 1
- 9 0
- 10 0
- 11 0
- 12 90 Z
- 13 -101
- 14 1
- 15 0
- 16 -35
- 17 8
- 18 0
- 19 0
- 20 -88
- 21 -83
- 22 -85
- 23 -70 */
- await this.write(hhh);
- let hhhh = await slice.arrayBuffer();
- await this.write(hhhh);
- /*
- byteLength: 105306
- detached: false
- maxByteLength: 105306
- resizable : false*/
-
- ///////
-
- response_h = await this.read(24);
- /*
- Index Valeur (Int8) Interprétation ASCII
- 0 79 O
- 1 75 K
- 2 65 A
- 3 89 Y
- 4 1
- 5 0
- 6 0
- 7 0
- 8 1
- 9 0
- 10 0
- 11 0
- 12 0
- 13 0
- 14 0
- 15 0
- 16 0
- 17 0
- 18 0
- 19 0
- 20 -80
- 21 -76
- 22 -66
- 23 -90 */
- header = MessageHeader.parse(response_h, useChecksum);
- switch (header.cmd) {
- default: {
- if (header.length > 0) {
- receivedData = await this.read(header.length);
- } else {
- receivedData = new DataView(encoder.encode("0").buffer); // 1pass Here 2nd...
- }
- }
- }
- message = new MessageClass(header, receivedData);
-
- if (message.header.cmd !== 'OKAY') {
- throw new Error('WRTE Failed');
- }
-
- header = new MessageHeader('OKAY', localId, remoteId, 0, checksum);
- await this.write(header.toDataView().buffer);
-
- response_h = await this.read(24);
- /*
-
- Index Valeur (Int8) Interprétation ASCII
- 0 87 W
- 1 82 R
- 2 84 T
- 3 69 E
- 4 1
- 5 0
- 6 0
- 7 0
- 8 1
- 9 0
- 10 0
- 11 0
- 12 8
- 13 0
- 14 0
- 15 0
- 16 -128
- 17 1
- 18 0
- 19 0
- 20 -88
- 21 -83
- 22 -85
- 23 -70 */
- header = MessageHeader.parse(response_h, useChecksum);
- switch (header.cmd) {
- default: {
- if (header.length > 0) { // 1pass 8
- receivedData = await this.read(header.length);
- /*
- 0 48 0
- 1 48 0
- 2 48 0
- 3 48 0
- 4 48 0
- 5 48 0
- 6 48 0
- 7 48 0*/
- }
- }
- }
-
- message = new MessageClass(header, receivedData);
-
- if (message.header.cmd !== 'WRTE') {
- throw new Error('WRTE Failed');
- }
- }
- return true;
- }
-
- async adbOpen(blob, useChecksum) {
- // This one is used by the adb.bundle.js
-
- const encoder = new TextEncoder();
- const decoder = new TextDecoder();
-
- const MAX_PAYLOAD = 0x40000;
- const fileSize = blob.size;
- const service = `sideload-host:${fileSize}:${MAX_PAYLOAD}`; //sideload-host:1381604186:262144
-
- let data = new DataView(encoder.encode('' + service + '\0').buffer);
- this.stream = await this.webusb.createStream(service); // Send Open message and receive OKAY.
-
- let checksum = 0;
- if (useChecksum) {
- checksum = MessageClass.checksum(data);
- }
- const localId = this.stream.localId;
- const remoteId = this.stream.remoteId;
-
- let header = new MessageHeader('OKAY', localId, remoteId, 0, checksum);
- let receivedData, message;
- await this.adbWebBackend.write(header.toDataView().buffer);
- let r = await this.adbWebBackend.read(24);
- let v = Array.from(new Uint8Array(r)).map(byte => String.fromCharCode(byte)).join('');
- if (v[0]=='W' && v[1]=='R' && v[2]=='T' && v[3]=='E') {
- receivedData = await this.adbWebBackend.read(8);
- message = new MessageClass(header, receivedData);
- } else {
- throw new Error('Write OKAY Failed (init)');
- }
-
- while (true) {
- const res = decoder.decode(message.data);
- const block = Number(res);
-
- if (isNaN(block) && res === 'DONEDONE') {
- break;
- } else {
- if ((block%10)==0) {
- WDebug.log("Sideloading " + block);
- }
- }
-
- const offset = block * MAX_PAYLOAD;
- if (offset >= fileSize) {
- throw new Error(`adb: failed to read block ${block} past end`);
- }
-
- let to_write = MAX_PAYLOAD;
- if ((offset + MAX_PAYLOAD) > fileSize) {
- to_write = fileSize - offset;
- }
-
- let slice = blob.slice(offset, offset + to_write);
- header = new MessageHeader('WRTE', localId, remoteId, to_write, checksum);
- let buff = await slice.arrayBuffer();
-
- await this.adbWebBackend.write(header.toDataView().buffer)
- await this.adbWebBackend.write(buff);
- r = await this.adbWebBackend.read(24);
- v = Array.from(new Uint8Array(r)).map(byte => String.fromCharCode(byte)).join('');
- //test OKAY
- if (v[0]=='O' && v[1]=='K' && v[2]=='A' && v[3]=='Y') {
- header = new MessageHeader('OKAY', localId, remoteId, 0, checksum);
- await this.adbWebBackend.write(header.toDataView().buffer);
- r = await this.adbWebBackend.read(24);
- v = Array.from(new Uint8Array(r)).map(byte => String.fromCharCode(byte)).join('');
- //Test WRTE
- if (v[0]=='W' && v[1]=='R' && v[2]=='T' && v[3]=='E') {
- receivedData = await this.adbWebBackend.read(8);
- message = new MessageClass(header, receivedData);
- } else {
- throw new Error(`WRTE Failed ${block}`);
- }
- } else {
- throw new Error(`OKAY Failed ${block}`);
- }
- }
- return true;
- }
-}
+import { MessageClass } from "../../lib/webadb/message.class.js";
+import { MessageHeader } from "../../lib/webadb/message-header.class.js";
+import { Device } from "./device.class.js";
+import { WDebug } from "../../debug.js";
+import { AdbWebBackend3, Adb3 } from "../../lib/webadb/adb.bundle.js";
+
+export class Recovery extends Device {
+ constructor(device) {
+ super(device);
+ this.webusb = null;
+ this.count = 0;
+ this.adbWebBackend = null;
+ }
+
+ async isConnected() {
+ if (!this.device) {
+ return false;
+ }
+ try {
+ return this.device.getDevice();
+ } catch {
+ return false;
+ }
+ }
+
+ isRecovery() {
+ return true;
+ }
+
+ async connect() {
+ try {
+ if (this.device && this.device.isConnected) {
+ WDebug.log("Connect recovery the device is connected");
+ } else {
+ const adbWebBackend = await AdbWebBackend3.requestDevice();
+ WDebug.log("adbWebBackend = ", adbWebBackend);
+ const adbDevice = new Adb3(adbWebBackend, null); //adb.bundle.js
+ WDebug.log("adbDevice = ", adbDevice);
+ await adbDevice.connect();
+ WDebug.log("adbDevice connected");
+ this.device = adbWebBackend._device;
+ this.webusb = adbDevice;
+ this.adbWebBackend = adbWebBackend;
+ }
+ } catch (e) {
+ this.device = null;
+ throw new Error(`Cannot connect Recovery ${e.message || e}`);
+ }
+ }
+
+ async sideload(blob) {
+ try {
+ await this.adbOpen(blob, true);
+ } catch (e) {
+ throw new Error(`Sideload fails ${e.message || e}`);
+ }
+ }
+
+ async reboot(mode) {
+ return await this.device.shell(`reboot ${mode}`);
+ }
+
+ getProductName() {
+ return this.webusb.name;
+ }
+
+ getSerialNumber() {
+ return this.webusb.product;
+ }
+
+ async adbOpen(blob, useChecksum) {
+ // This one is used by the adb.bundle.js
+
+ const encoder = new TextEncoder();
+ const decoder = new TextDecoder();
+
+ const MAX_PAYLOAD = 0x40000;
+ const fileSize = blob.size;
+ const service = `sideload-host:${fileSize}:${MAX_PAYLOAD}`; //sideload-host:1381604186:262144
+
+ let data = new DataView(encoder.encode("" + service + "\0").buffer);
+ this.stream = await this.webusb.createStream(service); // Send Open message and receive OKAY.
+
+ let checksum = 0;
+ if (useChecksum) {
+ checksum = MessageClass.checksum(data);
+ }
+ const localId = this.stream.localId;
+ const remoteId = this.stream.remoteId;
+
+ let header = new MessageHeader("OKAY", localId, remoteId, 0, checksum);
+ let receivedData, message;
+ await this.adbWebBackend.write(header.toDataView().buffer);
+ let r = await this.adbWebBackend.read(24);
+ let v = Array.from(new Uint8Array(r))
+ .map((byte) => String.fromCharCode(byte))
+ .join("");
+ if (v[0] == "W" && v[1] == "R" && v[2] == "T" && v[3] == "E") {
+ receivedData = await this.adbWebBackend.read(8);
+ message = new MessageClass(header, receivedData);
+ } else {
+ throw new Error("Write OKAY Failed (init)");
+ }
+
+ while (true) {
+ const res = decoder.decode(message.data);
+ const block = Number(res);
+
+ if (isNaN(block) && res === "DONEDONE") {
+ break;
+ } else {
+ if (block % 10 == 0) {
+ WDebug.log("Sideloading " + block);
+ }
+ }
+
+ const offset = block * MAX_PAYLOAD;
+ if (offset >= fileSize) {
+ throw new Error(`adb: failed to read block ${block} past end`);
+ }
+
+ let to_write = MAX_PAYLOAD;
+ if (offset + MAX_PAYLOAD > fileSize) {
+ to_write = fileSize - offset;
+ }
+
+ let slice = blob.slice(offset, offset + to_write);
+ header = new MessageHeader("WRTE", localId, remoteId, to_write, checksum);
+ let buff = await slice.arrayBuffer();
+
+ await this.adbWebBackend.write(header.toDataView().buffer);
+ await this.adbWebBackend.write(buff);
+ r = await this.adbWebBackend.read(24);
+ v = Array.from(new Uint8Array(r))
+ .map((byte) => String.fromCharCode(byte))
+ .join("");
+ //test OKAY
+ if (v[0] == "O" && v[1] == "K" && v[2] == "A" && v[3] == "Y") {
+ header = new MessageHeader("OKAY", localId, remoteId, 0, checksum);
+ await this.adbWebBackend.write(header.toDataView().buffer);
+ r = await this.adbWebBackend.read(24);
+ v = Array.from(new Uint8Array(r))
+ .map((byte) => String.fromCharCode(byte))
+ .join("");
+ //Test WRTE
+ if (v[0] == "W" && v[1] == "R" && v[2] == "T" && v[3] == "E") {
+ receivedData = await this.adbWebBackend.read(8);
+ message = new MessageClass(header, receivedData);
+ } else {
+ throw new Error(`WRTE Failed ${block}`);
+ }
+ } else {
+ throw new Error(`OKAY Failed ${block}`);
+ }
+ }
+ return true;
+ }
+}
diff --git a/app/src/controller/downloader.manager.js b/app/src/controller/downloader.manager.js
index c8d6a561d625aac6dc01db28464d17c675278c1e..8940e777ba5e8af86c27a8bb7b8f65b30d89717e 100644
--- a/app/src/controller/downloader.manager.js
+++ b/app/src/controller/downloader.manager.js
@@ -1,9 +1,8 @@
const DB_NAME = "MurenaBlobStore";
const DB_VERSION = 1;
-import ky from 'ky';
-import {ZipReader, BlobReader, BlobWriter} from "@zip.js/zip.js";
-import { WDebug } from "../debug.js";
+import ky from "ky";
+import { ZipReader, BlobReader, BlobWriter } from "@zip.js/zip.js";
/**
* Download Manager
@@ -12,238 +11,253 @@ import { WDebug } from "../debug.js";
* Blobs are in this.files[filename]
*/
export class Downloader {
- constructor() {
- this.db = null;
- this.stored = {};
- }
+ constructor() {
+ this.db = null;
+ this.stored = {};
+ }
- async init() {
- if (this.db) return; // Already initialized
+ async init() {
+ if (this.db) return; // Already initialized
- this.db = await this.openDBStore();
- await this.clearDBStore();
- this.quota = await navigator.storage.estimate();
- }
+ this.db = await this.openDBStore();
+ await this.clearDBStore();
+ this.quota = await navigator.storage.estimate();
+ }
- /*
- * */
- async downloadAndUnzipFolder(filesRequired, folder, onDownloadProgress, onUnzipProgress) {
- let current_file ;
- try {
- for (let i = 0; i < folder.length; i++) {
- const file = folder[i];
- current_file = file.path;
- if(filesRequired.includes(file.name) || file.unzip){
- const blob = await this.download(file.path, (value, total) => {
- onDownloadProgress(value, total, file.name);
- });
- if(file.unzip){
- const zipReader = new ZipReader(new BlobReader(blob));
- const filesEntries = await zipReader.getEntries();
- for(let i= 0 ; i < filesEntries.length; i++) {
- const unzippedEntry = await this.getFileFromZip(filesEntries[i], (value, total) => {
- onUnzipProgress(value, total, filesEntries[i].filename);
- });
- let filename = this.getMappedName(filesEntries[i].filename, file.mapping);
- if(filesRequired.includes(filename)){
- await this.setInDBStore(unzippedEntry.blob, filename);
- this.stored[filename] = true;
- }
- }
- await zipReader.close();
-
- } else {
- await this.setInDBStore(blob, file.name);
- this.stored[file.name] = true;
- }
- }
+ /*
+ * */
+ async downloadAndUnzipFolder(
+ filesRequired,
+ folder,
+ onDownloadProgress,
+ onUnzipProgress,
+ ) {
+ let current_file;
+ try {
+ for (let i = 0; i < folder.length; i++) {
+ const file = folder[i];
+ current_file = file.path;
+ if (filesRequired.includes(file.name) || file.unzip) {
+ const blob = await this.download(file.path, (value, total) => {
+ onDownloadProgress(value, total, file.name);
+ });
+ if (file.unzip) {
+ const zipReader = new ZipReader(new BlobReader(blob));
+ const filesEntries = await zipReader.getEntries();
+ for (let i = 0; i < filesEntries.length; i++) {
+ const unzippedEntry = await this.getFileFromZip(
+ filesEntries[i],
+ (value, total) => {
+ onUnzipProgress(value, total, filesEntries[i].filename);
+ },
+ );
+ let filename = this.getMappedName(
+ filesEntries[i].filename,
+ file.mapping,
+ );
+ if (filesRequired.includes(filename)) {
+ await this.setInDBStore(unzippedEntry.blob, filename);
+ this.stored[filename] = true;
+ }
}
- } catch (e) {
- throw new Error(`downloadAndUnzipFolder Error
current_file ${current_file}
${e.message || e}`);
- }
- }
-
- async getFileFromZip(file, onProgress) {
- const name = file.filename;
- const blob = await file.getData(new BlobWriter(), {
- onprogress: (value, total) => {
- onProgress(value, total, name);
- },
- useWebWorkers: false,
- });
- return {
- name,
- blob
+ await zipReader.close();
+ } else {
+ await this.setInDBStore(blob, file.name);
+ this.stored[file.name] = true;
+ }
}
+ }
+ } catch (e) {
+ throw new Error(
+ `downloadAndUnzipFolder Error
current_file ${current_file}
${e.message || e}`,
+ );
}
+ }
- getMappedName(filename, map) {
- if (!map) {
- return filename;
- }
+ async getFileFromZip(file, onProgress) {
+ const name = file.filename;
+ const blob = await file.getData(new BlobWriter(), {
+ onprogress: (value, total) => {
+ onProgress(value, total, name);
+ },
+ useWebWorkers: false,
+ });
+ return {
+ name,
+ blob,
+ };
+ }
- console.log(map);
- for (const [regex, newFilename] of Object.entries(map)) {
- let re = new RegExp(regex);
- if (filename.match(re)) {
- return newFilename;
- }
- }
- return filename;
+ getMappedName(filename, map) {
+ if (!map) {
+ return filename;
}
-
- /**
- * @param name
- * @returns {}
- * It does not launch download (downloads are launched with downloadFolder)
- * this function retrieve the promise linked to the fileName
- */
- async getFile(name) {
- const file = this.stored[name];
- if(!file){
- throw new Error(`File ${name} was not previously downloaded`)
- }
- return await this.getFromDBStore(name);
+ console.log(map);
+ for (const [regex, newFilename] of Object.entries(map)) {
+ let re = new RegExp(regex);
+ if (filename.match(re)) {
+ return newFilename;
+ }
}
+ return filename;
+ }
- /*
- * getData from a zip file
- * */
- async getData(dbFile, fileEntry, onProgress) {
- const _zip = new BlobWriter();
- const blob = await fileEntry.getData(_zip, {
- onprogress: (value, total) => {
- onProgress(value, total, dbFile);
- },
- onend: () => {},
- useWebWorkers: true,
- });
- return blob;
+ /**
+ * @param name
+ * @returns {}
+ * It does not launch download (downloads are launched with downloadFolder)
+ * this function retrieve the promise linked to the fileName
+ */
+ async getFile(name) {
+ const file = this.stored[name];
+ if (!file) {
+ throw new Error(`File ${name} was not previously downloaded`);
}
+ return await this.getFromDBStore(name);
+ }
- async download(path, onProgress) {
- try {
- const buffers = await this.fetch({
- url: path,
- chunkSize: 16 * 1024 * 1024,
- poolLimit: 1,
- }, onProgress);
-
- //let totalSize = buffers.reduce((sum, buffer) => sum + buffer.byteLength, 0);
- const ret = new Blob(buffers);
- return ret;
- } catch (e) {
- throw new Error(`${e.message || e}`);
- }
- }
+ /*
+ * getData from a zip file
+ * */
+ async getData(dbFile, fileEntry, onProgress) {
+ const _zip = new BlobWriter();
+ const blob = await fileEntry.getData(_zip, {
+ onprogress: (value, total) => {
+ onProgress(value, total, dbFile);
+ },
+ onend: () => {},
+ useWebWorkers: true,
+ });
+ return blob;
+ }
+
+ async download(path, onProgress) {
+ try {
+ const buffers = await this.fetch(
+ {
+ url: path,
+ chunkSize: 16 * 1024 * 1024,
+ poolLimit: 1,
+ },
+ onProgress,
+ );
- async clearDBStore() {
- const store = this.db.transaction(DB_NAME, "readwrite").objectStore(DB_NAME);
- store.clear();
+ //let totalSize = buffers.reduce((sum, buffer) => sum + buffer.byteLength, 0);
+ const ret = new Blob(buffers);
+ return ret;
+ } catch (e) {
+ throw new Error(`${e.message || e}`);
}
+ }
- async setInDBStore(blob, key) {
- return new Promise((resolve, reject) => {
- const transaction = this.db.transaction(DB_NAME, 'readwrite');
- const store = transaction.objectStore(DB_NAME);
- const request = store.put(blob, key);
+ async clearDBStore() {
+ const store = this.db
+ .transaction(DB_NAME, "readwrite")
+ .objectStore(DB_NAME);
+ store.clear();
+ }
- request.onsuccess = () => {
- resolve();
- };
+ async setInDBStore(blob, key) {
+ return new Promise((resolve, reject) => {
+ const transaction = this.db.transaction(DB_NAME, "readwrite");
+ const store = transaction.objectStore(DB_NAME);
+ const request = store.put(blob, key);
- request.onerror = (event) => {
- reject(event.target.error);
- };
- });
- }
+ request.onsuccess = () => {
+ resolve();
+ };
- async getFromDBStore(key) {
- return new Promise((resolve, reject) => {
- const transaction = this.db.transaction(DB_NAME, 'readonly');
- const store = transaction.objectStore(DB_NAME);
- const request = store.get(key);
- request.onsuccess = function (event) {
- const result = event.target.result;
- if (result) {
- resolve(result);
- } else {
- resolve(null);
- }
- };
- request.onerror = function (event) {
- reject(event.target.error);
- };
- });
- }
+ request.onerror = (event) => {
+ reject(event.target.error);
+ };
+ });
+ }
- async openDBStore() {
- return new Promise((resolve, reject) => {
- const request = indexedDB.open(DB_NAME, DB_VERSION);
- request.onerror = reject;
- request.onupgradeneeded = function (event) {
- const db = event.target.result;
- db.createObjectStore(DB_NAME, {autoIncrement: false});
- };
- request.onsuccess = function (event) {
- resolve(event.target.result);
- }
- });
- }
+ async getFromDBStore(key) {
+ return new Promise((resolve, reject) => {
+ const transaction = this.db.transaction(DB_NAME, "readonly");
+ const store = transaction.objectStore(DB_NAME);
+ const request = store.get(key);
+ request.onsuccess = function (event) {
+ const result = event.target.result;
+ if (result) {
+ resolve(result);
+ } else {
+ resolve(null);
+ }
+ };
+ request.onerror = function (event) {
+ reject(event.target.error);
+ };
+ });
+ }
+ async openDBStore() {
+ return new Promise((resolve, reject) => {
+ const request = indexedDB.open(DB_NAME, DB_VERSION);
+ request.onerror = reject;
+ request.onupgradeneeded = function (event) {
+ const db = event.target.result;
+ db.createObjectStore(DB_NAME, { autoIncrement: false });
+ };
+ request.onsuccess = function (event) {
+ resolve(event.target.result);
+ };
+ });
+ }
- concatenate(arrays) {
- if (!arrays.length) return null;
- let totalLength = arrays.reduce((acc, value) => acc + value.length, 0);
- let result = new Uint8Array(totalLength);
- let length = 0;
- for (let array of arrays) {
- result.set(array, length);
- length += array.length;
- }
- return result;
+ concatenate(arrays) {
+ if (!arrays.length) return null;
+ let totalLength = arrays.reduce((acc, value) => acc + value.length, 0);
+ let result = new Uint8Array(totalLength);
+ let length = 0;
+ for (let array of arrays) {
+ result.set(array, length);
+ length += array.length;
}
+ return result;
+ }
- async getContentLength(url) {
- const response = await ky.head(url)
- const contentLength = response.headers.get("content-length");
- return parseInt(contentLength, 10);
- }
+ async getContentLength(url) {
+ const response = await ky.head(url);
+ const contentLength = response.headers.get("content-length");
+ return parseInt(contentLength, 10);
+ }
- async fetch({url, chunkSize}, onProgress) {
+ async fetch({ url, chunkSize }, onProgress) {
+ try {
+ const contentLength = await this.getContentLength(url);
+ const totalChunks = Math.ceil(contentLength / chunkSize);
+ const buffers = [];
+
+ for (let i = 0; i < totalChunks; i++) {
+ const start = i * chunkSize;
+ const end = Math.min(start + chunkSize - 1, contentLength - 1);
try {
- const contentLength = await this.getContentLength(url);
- const totalChunks = Math.ceil(contentLength / chunkSize);
- const buffers = [];
-
- for (let i = 0; i < totalChunks; i++) {
- const start = i * chunkSize;
- const end = Math.min(start + chunkSize - 1, contentLength - 1);
- try {
- const response = await ky.get(url, {
- headers: {
- 'Range': `bytes=${start}-${end}`
- }
- });
- if (!response.ok) {
- throw new Error(`Cannot download chunk (1) ${i + 1}: ${response.status} ${response.statusText}`);
- }
-
- const chunk = await response.arrayBuffer();
- buffers.push(chunk);
- onProgress(start + chunk.byteLength, contentLength);
-
- } catch (chunkError) {
- throw new Error(`Cannot download chunk (2) ${i + 1} ${chunkError.message || chunkError}`);
- }
- }
- return buffers;
-
- } catch (error) {
- throw new Error(`Download fails ${error.message || error}`);
+ const response = await ky.get(url, {
+ headers: {
+ Range: `bytes=${start}-${end}`,
+ },
+ });
+ if (!response.ok) {
+ throw new Error(
+ `Cannot download chunk (1) ${i + 1}: ${response.status} ${response.statusText}`,
+ );
+ }
+
+ const chunk = await response.arrayBuffer();
+ buffers.push(chunk);
+ onProgress(start + chunk.byteLength, contentLength);
+ } catch (chunkError) {
+ throw new Error(
+ `Cannot download chunk (2) ${i + 1} ${chunkError.message || chunkError}`,
+ );
}
+ }
+ return buffers;
+ } catch (error) {
+ throw new Error(`Download fails ${error.message || error}`);
}
-
-
+ }
}
diff --git a/app/src/controller/utils/step.class.js b/app/src/controller/utils/step.class.js
index f023094529b9cd29c0091df00a23c594a37ec220..f5dfdb3ed856b656c3a11951a6c6f512b18959f0 100644
--- a/app/src/controller/utils/step.class.js
+++ b/app/src/controller/utils/step.class.js
@@ -1,21 +1,20 @@
-import {Command} from "../device/command.class.js";
-
-export class Step {
- constructor(name, command, needUserGesture,mode) {
- this.name = name;
- this.id = new Date().getTime() + Math.round((Math.random() * 1000));
- this.needUserGesture = needUserGesture;
- this.commands = [];
- if(command) {
- if(Array.isArray(command)){
- this.commands = command.map(m => {
- return new Command(m)
- });
- } else {
- this.commands = [new Command(command)];
- }
- }
- this.mode = mode;
- }
-
-}
\ No newline at end of file
+import { Command } from "../device/command.class.js";
+
+export class Step {
+ constructor(name, command, needUserGesture, mode) {
+ this.name = name;
+ this.id = new Date().getTime() + Math.round(Math.random() * 1000);
+ this.needUserGesture = needUserGesture;
+ this.commands = [];
+ if (command) {
+ if (Array.isArray(command)) {
+ this.commands = command.map((m) => {
+ return new Command(m);
+ });
+ } else {
+ this.commands = [new Command(command)];
+ }
+ }
+ this.mode = mode;
+ }
+}
diff --git a/app/src/debug.js b/app/src/debug.js
index a90c247467da791d9d10a95fed411e2977a8d4e9..96d0e9d40711c3826e64890b4522e84f4a7bf7a1 100644
--- a/app/src/debug.js
+++ b/app/src/debug.js
@@ -1,10 +1,10 @@
export class WDebug {
- constructor() {}
-
- static log(...args) {
- console.log('[DEBUG]', ...args);
- }
- static error(...args) {
- console.error('[ERROR]', ...args);
- }
- }
\ No newline at end of file
+ constructor() {}
+
+ static log(...args) {
+ console.log("[DEBUG]", ...args);
+ }
+ static error(...args) {
+ console.error("[ERROR]", ...args);
+ }
+}
diff --git a/app/src/errorManager.js b/app/src/errorManager.js
index 162bf02293d571f3f40fb3b3816723206078cad5..d55b7baaa2607ce70f102a1944b0ad9f5b0ccbc3 100644
--- a/app/src/errorManager.js
+++ b/app/src/errorManager.js
@@ -1,11 +1,11 @@
/*
- * Copyright 2024 - ECORP SAS
+ * Copyright 2024 - ECORP SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -16,24 +16,22 @@
*/
/*
-* Class to manage errors
-* The Error are NOT translated, as the may not be predicted in all the case
-*/
+ * Class to manage errors
+ * The Error are NOT translated, as the may not be predicted in all the case
+ */
export class ErrorManager {
- constructor() {
- }
-
- // Display a message relative to when the installer is (Step)
- static displayError_state(caption, message) {
- document.getElementById('error-message-state').style.display = 'block';
- console.log("-------------------DISPLAY ERROR ----------------");
- console.log(caption);
- console.log(message);
- console.log("-------------------------------------------------");
- const errorCaption = document.getElementById('error-caption-state');
- const errorText = document.getElementById('error-text-state');
- errorCaption.innerHTML = caption;
- errorText.innerHTML = message;
- }
+ constructor() {}
-}
\ No newline at end of file
+ // Display a message relative to when the installer is (Step)
+ static displayError_state(caption, message) {
+ document.getElementById("error-message-state").style.display = "block";
+ console.log("-------------------DISPLAY ERROR ----------------");
+ console.log(caption);
+ console.log(message);
+ console.log("-------------------------------------------------");
+ const errorCaption = document.getElementById("error-caption-state");
+ const errorText = document.getElementById("error-text-state");
+ errorCaption.innerHTML = caption;
+ errorText.innerHTML = message;
+ }
+}
diff --git a/app/src/viewManager.js b/app/src/viewManager.js
index f9ed2141ab8cee899f6a210e0868afea1f86d624..f6f7e02beda3d4efd55bbc884716b17d0939f067 100644
--- a/app/src/viewManager.js
+++ b/app/src/viewManager.js
@@ -1,209 +1,221 @@
-import {WDebug} from './debug.js'
-import {ErrorManager} from './errorManager.js'
-import {Controller} from './controller.manager.js';
-import {TranslationManager} from './vue/translation.manager.js';
-
-/*
-* Class to manage events
-* from the buttons events to the event of the controller and fastboot
-* it's just log for now, but maybe it will be more usefull for dynamic display
-*/
-
-export default class ViewManager {
-
- constructor() {
-
- }
-
- async init() {
- this.WDebug = WDebug;
- this.ErrorManager = ErrorManager;
- this.controller = new Controller();
- await this.controller.init(this);
- this.translationManager = new TranslationManager();
- await this.translationManager.init();
- window.scroll(0,0);
- }
-
- selectStep(currentIndex, step) {
- const $stepIndex = document.getElementById('current-step');
- $stepIndex.innerText = currentIndex+1;
-
- const $step = document.getElementById(step.name);
- if ($step) {
- const $copyStep = $step.cloneNode(true);
- $copyStep.id = step.id;
- $copyStep.classList.add('active');
- $copyStep.classList.remove('inactive');
- $copyStep.addEventListener('click', async () => {
- this.executeStep($copyStep, step.name);
- });
- let $processCtn = document.getElementById('process-ctn');
- if($processCtn){
- $processCtn.appendChild($copyStep);
- setTimeout(() => {
- $copyStep.scrollIntoView({ behavior: "smooth", block: "start"});
- }, 100);
- }
- }
- }
-
- updateTotalStep(total){
- const $total = document.getElementById('total-step');
- $total.innerText = total;
- }
- // BUTTON EVENTS
-
- async onNext($button) {
- $button.disabled = true;
- try {
- await this.controller.next();
- } catch (e) {
- this.ErrorManager.displayError_state('Error on next', `${e.message || e}`);
- $button.disabled = false;
- } finally {
- }
- }
- async executeStep($button, stepName) {
- $button.disabled = true;
- let loader = $button.querySelector('.btn-loader');
- if(loader) {
- loader.style.display = 'inline-block';
- }
-
- try {
- await this.controller.executeStep(stepName, loader);
- } catch (e) {
- this.ErrorManager.displayError_state(`Error on step: ${stepName}`, `${e.message || e}`);
- $button.disabled = false;
- } finally {
- if(loader) {
- loader.style.display = 'none';
- }
- }
-
- }
- onStepStarted(currentIndex, currentStep) {
- this.selectStep(currentIndex, currentStep);
- }
-
- onStepFinished(currentStep, nextStep) {
- if (currentStep) {
- const $currentStep = document.getElementById(currentStep.id);
- if($currentStep){
- const $button = $currentStep.getElementsByClassName('next');
- const $check = document.createElement('IMG');
- $check.src = "assets/images/icons/check.svg";
- if($button[0]){
- $button[0].replaceWith($check);
- }
-
- $currentStep.classList.add('done');
- $currentStep.classList.remove('active');
- }
- }
- if (nextStep) {
- /*const $next = document.getElementById(nextStep.id);
- $next.disabled = !nextStep.needUser;*/
- }
- }
- onStepFailed(step){
-
- }
-
- // /BUTTON EVENTS
-
- /*
- * STEP 1 : Connect
- */
- onADBConnect() {
- this.WDebug.log(`Device connected !`);
- }
-
- async onWaiting() {
- this.WDebug.log(`.`);
- }
-
- onDownloading(name, loaded, total) {
- const v = Math.round(loaded / total * 100) ;
- let $progressBar = document.querySelector(`.active .downloading-progress-bar`);
- let $progress = document.querySelector(`.active .downloading-progress`);
- if ($progressBar) {
- $progressBar.value = v;
- }
- if ($progress) {
- $progress.innerText = `Downloading ${name}: ${v}/${100}`;
- }
- this.WDebug.log(`Downloading ${name}: ${v}/${100}`, `downloading-${name}`);
- }
-
- onUnzip(name, loaded, total) {
- const v = Math.round(loaded / total * 100) ;
- let $progressBar = document.querySelector(`.active .downloading-progress-bar`);
- let $progress = document.querySelector(`.active .downloading-progress`);
- if ($progressBar) {
- $progressBar.value = v;
- }
- if ($progress) {
- $progress.innerText = `Extracting ${name}: ${v}/${100}`;
- }
- this.WDebug.log(`Unzipping ${name}: ${v}/${100}`, `Unzipping-${name}`);
- }
- onDownloadingEnd() {
- let $progressBar = document.querySelector(`.active .downloading-progress-bar`);
- if ($progressBar) {
- $progressBar.classList.add('success');
- }
- let $progress = document.querySelector(`.active .downloading-progress`);
- if ($progress) {
- $progress.innerText = `Download is complete!`;
- }
- let $ready = document.querySelector(`.active .ready-to-install-e-os `);
- if ($ready) {
- $ready.style.display = `block`;
- }
- }
-
- async onInstalling(name, loaded, total) {
- const v = Math.round(loaded / total * 100) ;
- let $progressBar = document.querySelector(`.active .installing-progress-bar`);
- let $progress = document.querySelector(`.active .installing-progress`);
- if ($progressBar) {
- $progressBar.value = v;
- }
- if ($progress) {
- $progress.innerText = `Installing ${name}: ${v}/${100}`;
- }
- this.WDebug.log(`Installing ${name}: ${Math.round(v * 100)}/${100}`, `installing-${name}`);
- }
- updateData(key, value){
- let $subscribers = document.querySelectorAll(`[data-subscribe="${key}"]`);
- this.WDebug.log($subscribers);
- this.WDebug.log({
- [key] : value
- });
- for(let i = 0 ; i< $subscribers.length; i++) {
- this.translationManager.translateElement($subscribers[i], {
- [key] : value
- })
- }
- }
-
- // /CONTROLLER EVENTS
-}
-
-document.addEventListener('DOMContentLoaded', async () => {
- var VIEW = new ViewManager();
- await VIEW.init();
-
- let elts = document.querySelectorAll(".card button")
- for(let elt of elts) {
- if (elt.parentElement.parentElement.className.includes("inactive")) {
- continue;
- }
- elt.addEventListener('click', async () => {
- VIEW.executeStep(elt, elt.parentElement.parentElement.id);
- })
- }
-
-});
+import { WDebug } from "./debug.js";
+import { ErrorManager } from "./errorManager.js";
+import { Controller } from "./controller.manager.js";
+import { TranslationManager } from "./vue/translation.manager.js";
+
+/*
+ * Class to manage events
+ * from the buttons events to the event of the controller and fastboot
+ * it's just log for now, but maybe it will be more useful for dynamic display
+ */
+
+export default class ViewManager {
+ constructor() {}
+
+ async init() {
+ this.WDebug = WDebug;
+ this.ErrorManager = ErrorManager;
+ this.controller = new Controller();
+ await this.controller.init(this);
+ this.translationManager = new TranslationManager();
+ await this.translationManager.init();
+ window.scroll(0, 0);
+ }
+
+ selectStep(currentIndex, step) {
+ const $stepIndex = document.getElementById("current-step");
+ $stepIndex.innerText = currentIndex + 1;
+
+ const $step = document.getElementById(step.name);
+ if ($step) {
+ const $copyStep = $step.cloneNode(true);
+ $copyStep.id = step.id;
+ $copyStep.classList.add("active");
+ $copyStep.classList.remove("inactive");
+ $copyStep.addEventListener("click", async () => {
+ this.executeStep($copyStep, step.name);
+ });
+ let $processCtn = document.getElementById("process-ctn");
+ if ($processCtn) {
+ $processCtn.appendChild($copyStep);
+ setTimeout(() => {
+ $copyStep.scrollIntoView({
+ behavior: "smooth",
+ block: "start",
+ });
+ }, 100);
+ }
+ }
+ }
+
+ updateTotalStep(total) {
+ const $total = document.getElementById("total-step");
+ $total.innerText = total;
+ }
+ // BUTTON EVENTS
+
+ async onNext($button) {
+ $button.disabled = true;
+ try {
+ await this.controller.next();
+ } catch (e) {
+ this.ErrorManager.displayError_state(
+ "Error on next",
+ `${e.message || e}`,
+ );
+ $button.disabled = false;
+ }
+ }
+ async executeStep($button, stepName) {
+ $button.disabled = true;
+ let loader = $button.querySelector(".btn-loader");
+ if (loader) {
+ loader.style.display = "inline-block";
+ }
+
+ try {
+ await this.controller.executeStep(stepName, loader);
+ } catch (e) {
+ this.ErrorManager.displayError_state(
+ `Error on step: ${stepName}`,
+ `${e.message || e}`,
+ );
+ $button.disabled = false;
+ } finally {
+ if (loader) {
+ loader.style.display = "none";
+ }
+ }
+ }
+ onStepStarted(currentIndex, currentStep) {
+ this.selectStep(currentIndex, currentStep);
+ }
+
+ onStepFinished(currentStep, nextStep) {
+ if (currentStep) {
+ const $currentStep = document.getElementById(currentStep.id);
+ if ($currentStep) {
+ const $button = $currentStep.getElementsByClassName("next");
+ const $check = document.createElement("IMG");
+ $check.src = "assets/images/icons/check.svg";
+ if ($button[0]) {
+ $button[0].replaceWith($check);
+ }
+
+ $currentStep.classList.add("done");
+ $currentStep.classList.remove("active");
+ }
+ }
+ if (nextStep) {
+ /*const $next = document.getElementById(nextStep.id);
+ $next.disabled = !nextStep.needUser;*/
+ }
+ }
+ onStepFailed() {}
+
+ // /BUTTON EVENTS
+
+ /*
+ * STEP 1 : Connect
+ */
+ onADBConnect() {
+ this.WDebug.log(`Device connected !`);
+ }
+
+ async onWaiting() {
+ this.WDebug.log(`.`);
+ }
+
+ onDownloading(name, loaded, total) {
+ const v = Math.round((loaded / total) * 100);
+ let $progressBar = document.querySelector(
+ `.active .downloading-progress-bar`,
+ );
+ let $progress = document.querySelector(`.active .downloading-progress`);
+ if ($progressBar) {
+ $progressBar.value = v;
+ }
+ if ($progress) {
+ $progress.innerText = `Downloading ${name}: ${v}/${100}`;
+ }
+ this.WDebug.log(`Downloading ${name}: ${v}/${100}`, `downloading-${name}`);
+ }
+
+ onUnzip(name, loaded, total) {
+ const v = Math.round((loaded / total) * 100);
+ let $progressBar = document.querySelector(
+ `.active .downloading-progress-bar`,
+ );
+ let $progress = document.querySelector(`.active .downloading-progress`);
+ if ($progressBar) {
+ $progressBar.value = v;
+ }
+ if ($progress) {
+ $progress.innerText = `Extracting ${name}: ${v}/${100}`;
+ }
+ this.WDebug.log(`Unzipping ${name}: ${v}/${100}`, `Unzipping-${name}`);
+ }
+ onDownloadingEnd() {
+ let $progressBar = document.querySelector(
+ `.active .downloading-progress-bar`,
+ );
+ if ($progressBar) {
+ $progressBar.classList.add("success");
+ }
+ let $progress = document.querySelector(`.active .downloading-progress`);
+ if ($progress) {
+ $progress.innerText = `Download is complete!`;
+ }
+ let $ready = document.querySelector(`.active .ready-to-install-e-os `);
+ if ($ready) {
+ $ready.style.display = `block`;
+ }
+ }
+
+ async onInstalling(name, loaded, total) {
+ const v = Math.round((loaded / total) * 100);
+ let $progressBar = document.querySelector(
+ `.active .installing-progress-bar`,
+ );
+ let $progress = document.querySelector(`.active .installing-progress`);
+ if ($progressBar) {
+ $progressBar.value = v;
+ }
+ if ($progress) {
+ $progress.innerText = `Installing ${name}: ${v}/${100}`;
+ }
+ this.WDebug.log(
+ `Installing ${name}: ${Math.round(v * 100)}/${100}`,
+ `installing-${name}`,
+ );
+ }
+ updateData(key, value) {
+ let $subscribers = document.querySelectorAll(`[data-subscribe="${key}"]`);
+ this.WDebug.log($subscribers);
+ this.WDebug.log({
+ [key]: value,
+ });
+ for (let i = 0; i < $subscribers.length; i++) {
+ this.translationManager.translateElement($subscribers[i], {
+ [key]: value,
+ });
+ }
+ }
+
+ // /CONTROLLER EVENTS
+}
+
+document.addEventListener("DOMContentLoaded", async () => {
+ var VIEW = new ViewManager();
+ await VIEW.init();
+
+ let elts = document.querySelectorAll(".card button");
+ for (let elt of elts) {
+ if (elt.parentElement.parentElement.className.includes("inactive")) {
+ continue;
+ }
+ elt.addEventListener("click", async () => {
+ VIEW.executeStep(elt, elt.parentElement.parentElement.id);
+ });
+ }
+});
diff --git a/app/src/vue/translation.manager.js b/app/src/vue/translation.manager.js
index d6de409d5df5f89a6f9b02801f2ea63bb9ad77fe..46afc00681d4d44c7bc16e8e9d4fdc4c5f2931c7 100644
--- a/app/src/vue/translation.manager.js
+++ b/app/src/vue/translation.manager.js
@@ -1,141 +1,141 @@
-/*
-* Class to manage translation
-* fetch translation file & use the correct language for the user
-* also change single Node text if needed
-* [data-translate] is used to find Nodes needing translation
-*/
-import {WDebug} from "../debug.js";
-
-export class TranslationManager {
- static DEFAULT = 'en'; //if user languages not found, fallback to 'en'
- constructor() {
- this.translation = {};
- this.values = {};
- this.languages = TranslationManager.getAcceptedLanguages();
- this.languageIndex = 0;
- }
-
- async init() {
- await this.loadCurrentTranslation(); // fetch translation
- await this.translateDOM();// use it for DOM
- }
- /**
- * @returns string
- * using the current languageIndex, we retrieve the string language
- * ex 'fr-FR'
- */
- getCurrentLanguage() {
- return this.languages[this.languageIndex];
- }
- async loadCurrentTranslation() {
- const language = this.getCurrentLanguage();
- const shortLanguage = TranslationManager.getShortLanguage(language);
- try {
- this.translation = await TranslationManager.fetchTranslation(shortLanguage);
- } catch(e) {
- //if language not found, fallback to next language
- if(this.languageIndex < this.languages.length) {
- this.languageIndex++;
- await this.loadCurrentTranslation();
- } else {
- //as the last language is the default app one, this should never happen... Right ?
- this.translation = {};
- }
- }
- }
- /**
- * select DOM elements using data-translate key
- * translate each DOM element elected
- */
- translateDOM() {
- const elems = document.querySelectorAll('[data-translate]');
- for (let i = 0; i < elems.length; i++) {
- this.translateElement(elems[i]);
- }
- }
-
-
- /**
- * get the translation using data-translate value
- * replace DOM HTML with the translation
- */
- translateElement($el, values) {
- if($el.dataset.translate) {
- $el.innerHTML = this.translate($el.dataset.translate, values);
- }
- }
- /**
- * @param key : string
- * @param values : object?
- * @returns string
- * using key to retrieve the wanted string in the translations
- * if values is a defined object, we use it to set value in the translation
- * ex: if values = { "hello" : "Hallo" } and translation = "{{hello}} Welt !"
- * returned text is "Hallo Welt !"
- */
- translate(key, values) {
- let text = this.translation[key];
- if (!text) {
- console.warn(`translation of ${key} not found`)
- text = key;
- }
- //I have to choose tags, so I'm using Mustache tags
- //I'm not adding the lib since it's not necessary
- //But if one day it is, the translation does not have to change :>
- if (typeof values === 'object') {
- Object.keys(values).forEach(k => {
- text = text.replaceAll(`{{${k}}}`, values[k]);
- });
- }
- return text;
- }
-
- /**
- * @param language : string
- * @returns string
- * return the short version of a language
- * ex: 'en-US' return 'en'
- */
- static getShortLanguage(language) {
- let shortLang = language;
- if (shortLang.indexOf('-') !== -1){
- shortLang = shortLang.split('-')[0];
- }
- if (shortLang.indexOf('_') !== -1){
- shortLang = shortLang.split('_')[0];
- }
- return shortLang;
- }
-
- /**
- * @param language : string
- * @returns JSON
- * fetch translation file and return its JSON content
- * throw error in case of file not found or invalid JSON content
- */
- static async fetchTranslation(language) {
- const response = await fetch(`assets/languages/${language}.json`);
- if(response.ok) {
- try {
- return await response.json();
- } catch (e) {
- WDebug.error("translation file is not a valid JSON: ", language);
- throw Error(`${language} translation file is not a valid JSON`);
- }
- } else { //Most likely a 404
- throw Error(`${language} not found`);
- }
- }
- /**
- * @returns string[]
- * get user's preferred languages
- * and add default translation app as the last one in case none of user's preferred languages are usable
- * ex ['ay', 'fr-FR', 'en-US', 'en']
- */
- static getAcceptedLanguages() {
- let languages = [...window.navigator.languages]; //use copy as window.navigator.languages is not editable
- languages.push(TranslationManager.DEFAULT); //add default language app as the last resort
- return languages;
- }
-
-}
\ No newline at end of file
+/*
+ * Class to manage translation
+ * fetch translation file & use the correct language for the user
+ * also change single Node text if needed
+ * [data-translate] is used to find Nodes needing translation
+ */
+import { WDebug } from "../debug.js";
+
+export class TranslationManager {
+ static DEFAULT = "en"; //if user languages not found, fallback to 'en'
+ constructor() {
+ this.translation = {};
+ this.values = {};
+ this.languages = TranslationManager.getAcceptedLanguages();
+ this.languageIndex = 0;
+ }
+
+ async init() {
+ await this.loadCurrentTranslation(); // fetch translation
+ await this.translateDOM(); // use it for DOM
+ }
+ /**
+ * @returns string
+ * using the current languageIndex, we retrieve the string language
+ * ex 'fr-FR'
+ */
+ getCurrentLanguage() {
+ return this.languages[this.languageIndex];
+ }
+ async loadCurrentTranslation() {
+ const language = this.getCurrentLanguage();
+ const shortLanguage = TranslationManager.getShortLanguage(language);
+ try {
+ this.translation =
+ await TranslationManager.fetchTranslation(shortLanguage);
+ } catch {
+ //if language not found, fallback to next language
+ if (this.languageIndex < this.languages.length) {
+ this.languageIndex++;
+ await this.loadCurrentTranslation();
+ } else {
+ //as the last language is the default app one, this should never happen... Right ?
+ this.translation = {};
+ }
+ }
+ }
+ /**
+ * select DOM elements using data-translate key
+ * translate each DOM element elected
+ */
+ translateDOM() {
+ const elems = document.querySelectorAll("[data-translate]");
+ for (let i = 0; i < elems.length; i++) {
+ this.translateElement(elems[i]);
+ }
+ }
+
+ /**
+ * get the translation using data-translate value
+ * replace DOM HTML with the translation
+ */
+ translateElement($el, values) {
+ if ($el.dataset.translate) {
+ $el.innerHTML = this.translate($el.dataset.translate, values);
+ }
+ }
+ /**
+ * @param key : string
+ * @param values : object?
+ * @returns string
+ * using key to retrieve the wanted string in the translations
+ * if values is a defined object, we use it to set value in the translation
+ * ex: if values = { "hello" : "Hallo" } and translation = "{{hello}} Welt !"
+ * returned text is "Hallo Welt !"
+ */
+ translate(key, values) {
+ let text = this.translation[key];
+ if (!text) {
+ console.warn(`translation of ${key} not found`);
+ text = key;
+ }
+ //I have to choose tags, so I'm using Mustache tags
+ //I'm not adding the lib since it's not necessary
+ //But if one day it is, the translation does not have to change :>
+ if (typeof values === "object") {
+ Object.keys(values).forEach((k) => {
+ text = text.replaceAll(`{{${k}}}`, values[k]);
+ });
+ }
+ return text;
+ }
+
+ /**
+ * @param language : string
+ * @returns string
+ * return the short version of a language
+ * ex: 'en-US' return 'en'
+ */
+ static getShortLanguage(language) {
+ let shortLang = language;
+ if (shortLang.indexOf("-") !== -1) {
+ shortLang = shortLang.split("-")[0];
+ }
+ if (shortLang.indexOf("_") !== -1) {
+ shortLang = shortLang.split("_")[0];
+ }
+ return shortLang;
+ }
+
+ /**
+ * @param language : string
+ * @returns JSON
+ * fetch translation file and return its JSON content
+ * throw error in case of file not found or invalid JSON content
+ */
+ static async fetchTranslation(language) {
+ const response = await fetch(`assets/languages/${language}.json`);
+ if (response.ok) {
+ try {
+ return await response.json();
+ } catch {
+ WDebug.error("translation file is not a valid JSON: ", language);
+ throw Error(`${language} translation file is not a valid JSON`);
+ }
+ } else {
+ //Most likely a 404
+ throw Error(`${language} not found`);
+ }
+ }
+ /**
+ * @returns string[]
+ * get user's preferred languages
+ * and add default translation app as the last one in case none of user's preferred languages are usable
+ * ex ['ay', 'fr-FR', 'en-US', 'en']
+ */
+ static getAcceptedLanguages() {
+ let languages = [...window.navigator.languages]; //use copy as window.navigator.languages is not editable
+ languages.push(TranslationManager.DEFAULT); //add default language app as the last resort
+ return languages;
+ }
+}
diff --git a/app/vite.config.js b/app/vite.config.js
index c5d471f453b92dea5499b0a7abf9984fdbfbc456..16ef1eca2b4fff59ccabfa1c7372cbb52c18d7fc 100644
--- a/app/vite.config.js
+++ b/app/vite.config.js
@@ -1,5 +1,5 @@
-import { defineConfig } from 'vite'
+import { defineConfig } from "vite";
export default defineConfig({
- base: '',
-})
+ base: "",
+});