Compare commits

...

208 Commits

Author SHA1 Message Date
Edwin Joassart
ec7e0b745e patch: send sourcemap to sentry at build 2023-01-12 17:46:00 +01:00
balenaCI
d5ba1ea5e1 v1.13.4 2023-01-12 15:10:51 +00:00
Balena CI
54d3636a22 Merge pull request #3890 from balena-io/wolvi-lataniere/adding-serial-number-etcher-pro
Adding EtcherPro device serial number to the Settings modal
2023-01-12 17:09:11 +02:00
Aurelien VALADE
45f6ee667d Cleaning-up EtcherPro specific code 2023-01-12 14:52:08 +01:00
Aurelien VALADE
d25eda9a7d Adding EtcherPro device serial number to the Settings modal
Change-type: patch
2023-01-12 12:12:10 +01:00
balenaCI
7420283249 v1.13.3 2023-01-11 14:30:46 +00:00
Balena CI
453952440f Merge pull request #3971 from balena-io/mcraa/win-cm4
patch: progress cm4 to second stage
2023-01-11 16:28:49 +02:00
Peter Makra
2475d576c7 patch: progress cm4 to second stage 2023-01-11 13:36:11 +01:00
balenaCI
8cd6da1260 v1.13.2 2023-01-02 20:55:59 +00:00
Balena CI
82dd4fc1d1 Merge pull request #3964 from balena-io/fix-winget-releaser
patch: fixed winget parameter name
2023-01-02 15:54:20 -05:00
mcraa
33fe4b2c1a patch: fixed winget parameter name 2023-01-02 21:17:55 +01:00
balenaCI
b1c1188107 v1.13.1 2023-01-02 17:26:57 +00:00
Balena CI
63b45aefae Merge pull request #3959 from balena-io/update-copyright
patch: update copyright in electron-builder
2023-01-02 12:25:24 -05:00
Peter Makra
f79cb0fac5 patch: updated sdk to fix bz2 issue 2023-01-02 17:44:42 +01:00
JOASSART Edwin
ec42892c7c patch: update copyright in electron-builder 2023-01-02 12:45:42 +01:00
balenaCI
371716fe6a v1.13.0 2022-12-28 16:48:14 +00:00
Balena CI
d5fb6bec15 Merge pull request #3945 from balena-io/update-sdk-for-cm4
Patch: update etcher-sdk version to fix CM4 issues
2022-12-28 11:46:52 -05:00
Peter Makra
c5e7bf26d7 bump electron deps 2022-12-23 21:32:30 +01:00
Peter Makra
e3072ac416 minor: electron version bump 2022-12-23 21:32:30 +01:00
Peter Makra
dfaf06e4cf sdk version bump 2022-12-23 21:32:29 +01:00
Peter Makra
6e24d25576 fixed ext2fs regex 2022-12-23 21:32:29 +01:00
Peter Makra
b59b171e43 patch: handle ext2fs with webpack 2022-12-23 21:32:29 +01:00
Peter Makra
28726584c2 prerelease etcher-compat etcher-sdk 2022-12-23 21:32:29 +01:00
Peter Makra
00b151311a alignerd webpack to ext2fs 2022-12-23 21:32:28 +01:00
builder555
36c813714b Patch: update etcher-sdk version to fix CM4 issues
Change-type: patch
2022-12-23 21:32:28 +01:00
balenaCI
2ae6764dd9 v1.12.7 2022-12-20 19:35:13 +00:00
Balena CI
debefc9652 Merge pull request #3954 from balena-io/renovate/i18next-21.x
Update dependency i18next to 21.10.0
2022-12-20 14:33:35 -05:00
Renovate Bot
b068b847c7 Update dependency i18next to 21.10.0
Update i18next to 21.10.0

Update i18next from 21.8.14 to 21.10.0

Change-type: patch
2022-12-20 18:56:45 +00:00
balenaCI
6c410c07ce v1.12.6 2022-12-20 18:00:05 +00:00
Balena CI
c01206c1f3 Merge pull request #3953 from balena-io/renovate/react-i18next-11.x
Update dependency react-i18next to 11.18.6
2022-12-20 12:58:30 -05:00
Renovate Bot
2e85fb45de Update dependency react-i18next to 11.18.6
Update react-i18next to 11.18.6

Update react-i18next from 11.18.1 to 11.18.6

Change-type: patch
2022-12-20 17:02:05 +00:00
balenaCI
67513e384d v1.12.5 2022-12-20 12:27:35 +00:00
Balena CI
828dafa493 Merge pull request #3950 from balena-io/easier-text-settings
Patch: made trim setting more readable
2022-12-20 07:26:13 -05:00
builder555
5c5a761222 Patch: made trim setting more readable
Change-type: patch
2022-12-20 06:52:06 -05:00
balenaCI
fab10e5fc5 v1.12.4 2022-12-19 19:42:01 +00:00
Balena CI
797345fc1c Merge pull request #3780 from balena-io/actions
patch: introducing github actions (WinGet)
2022-12-19 14:40:29 -05:00
Anton Belodedenko
a0388a43c3 Update winget.yml 2022-12-19 11:05:16 -08:00
mcraa
f5b0a3023b Update winget.yml 2022-12-19 11:05:16 -08:00
mcraa
dc1d7bd1fd fixed version of action to v1 2022-12-19 11:05:16 -08:00
Vedant
9d674321b6 Update winget.yml 2022-12-19 11:05:16 -08:00
Begula
f9c8378d6a patch: publish to winget with gh action 2022-12-19 11:05:16 -08:00
balenaCI
65da751a52 v1.12.3 2022-12-19 09:51:53 +00:00
Balena CI
72142be0de Merge pull request #3948 from balena-io/fix-i18n-settings
Patch: replaced plain text with i18n in settings
2022-12-19 04:50:25 -05:00
builder555
11cea7c926 Patch: replaced plain text with i18n in settings
Change-type: patch
2022-12-16 14:42:28 -05:00
balenaCI
8d46ee4c22 v1.12.2 2022-12-16 16:59:05 +00:00
Balena CI
d63c09e2c2 Merge pull request #3944 from balena-io/renovate/webpack-dev-server-4.x
Update dependency webpack-dev-server to 4.11.1
2022-12-16 11:56:45 -05:00
Renovate Bot
c9e9d7d109 Update dependency webpack-dev-server to 4.11.1
Update webpack-dev-server to 4.11.1

Update webpack-dev-server from 4.5.0 to 4.11.1

Change-type: patch
2022-12-16 15:57:46 +00:00
balenaCI
2412d20eb4 v1.12.1 2022-12-16 15:02:36 +00:00
Balena CI
7f90d23a12 Merge pull request #3947 from balena-io/expose-trim-setting
Patch: expose trim ext{2,3,4} setting
2022-12-16 09:59:32 -05:00
builder555
b9a82be29b Patch: expose trim ext{2,3,4} setting
Change-type: patch
2022-12-16 09:24:49 -05:00
balenaCI
638673ba5e v1.12.0 2022-12-14 16:17:32 +00:00
Balena CI
898fe4f216 Merge pull request #3936 from balena-io/i18n-conflict-resolve
I18n conflict resolve
2022-12-14 11:15:48 -05:00
Peter Makra
7e805662d1 check if modal children is aray 2022-12-14 15:48:48 +01:00
Peter Makra
baf59c73ac populated lockfile 2022-12-14 12:24:40 +01:00
mcraa
38ad9c97c6 added i18next to devDependencies 2022-12-14 12:03:30 +01:00
ab77
8fc574f059 i18n support and Chinese translation
Change-type: minor
2022-12-12 18:36:32 -08:00
r-q
78b0f00e88 chore: bind some translations
according to a suggestion of @lurch
2022-12-12 18:36:32 -08:00
r-q
0f10f2d483 fix: suit i18n with mocha and optimize translation
- use `import * as i18next from 'i18next';` instead of `import i18next from 'i18next';` and add an specific env to bypass mocha test
- optimized several translations
2022-12-12 18:36:32 -08:00
r-q
eb5f5bbb9e fix: optimize translations
more direct string-concatenation, thanks to @lurch
2022-12-12 18:36:32 -08:00
r-q
67d26ff790 minor: optimize i18n
Optimized several translations.
This commit itself is only a patch, but as a pull request must have at least one commit with a change-type.

Change-Type: minor
2022-12-12 18:36:32 -08:00
r-q
17f2008d88 refactor: split translations to files
- split translations from i18n.ts to several .ts files in lib/gui/app/i18n
- make a README for new language changes
- add zh-TW instead of only zh-CN
2022-12-12 18:36:32 -08:00
r-q
db1bf7e488 feat: make i18n and add Chinese support
- make i18n using i18next
- add Chinese (Simplified) support
2022-12-12 18:36:32 -08:00
balenaCI
4b786b8a9f v1.11.10 2022-12-13 02:27:43 +00:00
Balena CI
fdfa0d3258 Merge pull request #3943 from balena-io/renovate/webpack-cli-4.x
Update dependency webpack-cli to 4.10.0
2022-12-12 21:26:03 -05:00
Renovate Bot
757aa77d89 Update dependency webpack-cli to 4.10.0
Update webpack-cli to 4.10.0

Update webpack-cli from 4.2.0 to 4.10.0

Change-type: patch
2022-12-13 01:18:03 +00:00
balenaCI
d70ea06565 v1.11.9 2022-12-12 23:58:11 +00:00
Balena CI
f2ebd10053 Merge pull request #3941 from balena-io/renovate/webpack-5.x
Update dependency webpack to 5.75.0
2022-12-12 18:56:06 -05:00
Renovate Bot
cd67b442c9 Update dependency webpack to 5.75.0
Update webpack to 5.75.0

Update webpack from 5.11.0 to 5.75.0

Change-type: patch
2022-12-12 22:55:21 +00:00
balenaCI
852c83c4fb v1.11.8 2022-12-12 21:55:30 +00:00
Balena CI
e3b2ee3b83 Merge pull request #3940 from balena-io/renovate/awscli-1.x
Update dependency awscli to 1.27.28
2022-12-12 16:54:15 -05:00
Renovate Bot
927a026b86 Update dependency awscli to 1.27.28
Update awscli to 1.27.28

Update awscli from 1.27.27 to 1.27.28

Change-type: patch
2022-12-12 20:57:48 +00:00
balenaCI
c851e1d54f v1.11.7 2022-12-12 19:57:33 +00:00
Balena CI
e6fdca171f Merge pull request #3939 from balena-io/renovate/uuid-8.x
Update dependency uuid to 8.3.2
2022-12-12 14:56:00 -05:00
Renovate Bot
c9cfb87733 Update dependency uuid to 8.3.2
Update uuid to 8.3.2

Update uuid from 8.1.0 to 8.3.2

Change-type: patch
2022-12-12 18:56:41 +00:00
balenaCI
b0b7c53294 v1.11.6 2022-12-12 17:59:45 +00:00
Balena CI
e8dc6579fe Merge pull request #3933 from balena-io/renovate/tslib-2.x
Update dependency tslib to 2.4.1
2022-12-12 12:57:52 -05:00
Renovate Bot
f0747abe3f Update dependency tslib to 2.4.1
Update tslib to 2.4.1

Update tslib from 2.0.0 to 2.4.1

Change-type: patch
2022-12-12 16:59:52 +00:00
Balena CI
32fab87340 Merge pull request #3935 from balena-io/aethernet-buildUbuntu20
Patch: run linux build on ubuntu-20.04
2022-12-12 11:10:38 -05:00
Edwin Joassart
adcd8e0325 Patch: run linux build on ubuntu-20.04
as [`18.04` has been removed](https://github.blog/changelog/2022-08-09-github-actions-the-ubuntu-18-04-actions-runner-image-is-being-deprecated-and-will-be-removed-by-12-1-22/)

We cannot use `latest` as the glibc version will cause issue with older ubuntu version.
2022-12-12 12:09:01 +01:00
balenaCI
7b5808eb2b v1.11.5 2022-12-10 12:28:20 +00:00
Balena CI
a8f7422cf5 Merge pull request #3932 from balena-io/renovate/ts-loader-8.x
Update dependency ts-loader to 8.4.0
2022-12-10 07:26:55 -05:00
Renovate Bot
5ae9a26361 Update dependency ts-loader to 8.4.0
Update ts-loader to 8.4.0

Update ts-loader from 8.0.12 to 8.4.0

Change-type: patch
2022-12-10 11:57:20 +00:00
balenaCI
cf1fdb8c5f v1.11.4 2022-12-10 10:57:12 +00:00
Balena CI
bf7ebde100 Merge pull request #3930 from balena-io/renovate/styled-components-5.x
Update dependency styled-components to 5.3.6
2022-12-10 05:55:52 -05:00
Renovate Bot
88c5fa5035 Update dependency styled-components to 5.3.6
Update styled-components to 5.3.6

Update styled-components from 5.1.0 to 5.3.6

Change-type: patch
2022-12-10 09:57:26 +00:00
balenaCI
887b0dd538 v1.11.3 2022-12-10 08:54:54 +00:00
Balena CI
364d1db56a Merge pull request #3931 from balena-io/renovate/terser-webpack-plugin-5.x
Update dependency terser-webpack-plugin to 5.3.6
2022-12-10 03:53:34 -05:00
Renovate Bot
c431222909 Update dependency terser-webpack-plugin to 5.3.6
Update terser-webpack-plugin to 5.3.6

Update terser-webpack-plugin from 5.2.5 to 5.3.6

Change-type: patch
2022-12-10 07:54:55 +00:00
balenaCI
55a0f68b97 v1.11.2 2022-12-10 07:32:27 +00:00
Balena CI
af2563dfc2 Merge pull request #3929 from balena-io/renovate/string-replace-loader-3.x
Update dependency string-replace-loader to 3.1.0
2022-12-10 02:31:00 -05:00
Renovate Bot
33f8851083 Update dependency string-replace-loader to 3.1.0
Update string-replace-loader to 3.1.0

Update string-replace-loader from 3.0.1 to 3.1.0

Change-type: patch
2022-12-10 06:58:36 +00:00
balenaCI
fe1f19b9fa v1.11.1 2022-12-10 06:19:32 +00:00
Balena CI
871cf3ec0a Merge pull request #3928 from balena-io/renovate/sinon-9.x
Update dependency sinon to 9.2.4
2022-12-10 01:17:59 -05:00
Renovate Bot
686a5837b6 Update dependency sinon to 9.2.4
Update sinon to 9.2.4

Update sinon from 9.0.2 to 9.2.4

Change-type: patch
2022-12-10 04:58:08 +00:00
balenaCI
23f2dd5ce5 v1.11.0 2022-12-10 04:27:20 +00:00
Balena CI
d5d39b395b Merge pull request #3927 from balena-io/renovate/shyaml-0.x
Update dependency shyaml to 0.6.2
2022-12-09 23:25:51 -05:00
Renovate Bot
2acad790d3 Update dependency shyaml to 0.6.2
Update shyaml to 0.6.2

Update shyaml from 0.5.0 to 0.6.2

Change-type: minor
2022-12-10 03:56:23 +00:00
balenaCI
30133306d6 v1.10.29 2022-12-10 03:05:04 +00:00
Balena CI
04a62f2ad8 Merge pull request #3925 from balena-io/renovate/awscli-1.x
Update dependency awscli to 1.27.27
2022-12-09 22:03:25 -05:00
Renovate Bot
17858a7d72 Update dependency awscli to 1.27.27
Update awscli to 1.27.27

Update awscli from 1.27.26 to 1.27.27

Change-type: patch
2022-12-10 02:19:49 +00:00
balenaCI
620307568f v1.10.28 2022-12-10 02:10:44 +00:00
Balena CI
a349c5d9ac Merge pull request #3926 from balena-io/renovate/rendition-19.x
Update dependency rendition to 19.3.2
2022-12-09 21:08:52 -05:00
Renovate Bot
0d740ad12d Update dependency rendition to 19.3.2
Update rendition to 19.3.2

Update rendition from 19.2.0 to 19.3.2

Change-type: patch
2022-12-09 23:58:04 +00:00
balenaCI
85a3f28869 v1.10.27 2022-12-09 20:59:25 +00:00
Balena CI
dbd5397405 Merge pull request #3924 from balena-io/renovate/redux-4.x
Update dependency redux to 4.2.0
2022-12-09 15:57:56 -05:00
Renovate Bot
85c183b9ef Update dependency redux to 4.2.0
Update redux to 4.2.0

Update redux from 4.0.5 to 4.2.0

Change-type: patch
2022-12-09 19:58:31 +00:00
balenaCI
0d0af1d1dd v1.10.26 2022-12-09 18:58:23 +00:00
Balena CI
ad423fc187 Merge pull request #3923 from balena-io/renovate/pretty-bytes-5.x
Update dependency pretty-bytes to 5.6.0
2022-12-09 13:56:50 -05:00
Renovate Bot
d8b2a7a236 Update dependency pretty-bytes to 5.6.0
Update pretty-bytes to 5.6.0

Update pretty-bytes from 5.3.0 to 5.6.0

Change-type: patch
2022-12-09 18:00:18 +00:00
balenaCI
13ec8cbe98 v1.10.25 2022-12-09 17:01:54 +00:00
Balena CI
a7cae23612 Merge pull request #3922 from balena-io/renovate/pnp-webpack-plugin-1.x
Update dependency pnp-webpack-plugin to 1.7.0
2022-12-09 12:00:09 -05:00
Renovate Bot
86bb093f3d Update dependency pnp-webpack-plugin to 1.7.0
Update pnp-webpack-plugin to 1.7.0

Update pnp-webpack-plugin from 1.6.4 to 1.7.0

Change-type: patch
2022-12-09 16:01:26 +00:00
balenaCI
997e1eb2f2 v1.10.24 2022-12-09 14:59:56 +00:00
Balena CI
34cc8b8933 Merge pull request #3921 from balena-io/renovate/node-ipc-9.x
Update dependency node-ipc to 9.2.1
2022-12-09 09:58:26 -05:00
Renovate Bot
f26b074811 Update dependency node-ipc to 9.2.1
Update node-ipc to 9.2.1

Update node-ipc from 9.1.1 to 9.2.1

Change-type: patch
2022-12-09 13:56:52 +00:00
balenaCI
adaa07b4b0 v1.10.23 2022-12-09 13:05:54 +00:00
Balena CI
96f4569342 Merge pull request #3919 from balena-io/renovate/mocha-8.x
Update dependency mocha to 8.4.0
2022-12-09 08:04:01 -05:00
Renovate Bot
be190c6c80 Update dependency mocha to 8.4.0
Update mocha to 8.4.0

Update mocha from 8.0.1 to 8.4.0

Change-type: patch
2022-12-09 11:59:55 +00:00
balenaCI
809617a82d v1.10.22 2022-12-09 10:57:45 +00:00
Balena CI
df02732002 Merge pull request #3918 from balena-io/renovate/mini-css-extract-plugin-1.x
Update dependency mini-css-extract-plugin to 1.6.2
2022-12-09 05:56:17 -05:00
Renovate Bot
d35f3c3049 Update dependency mini-css-extract-plugin to 1.6.2
Update mini-css-extract-plugin to 1.6.2

Update mini-css-extract-plugin from 1.3.3 to 1.6.2

Change-type: patch
2022-12-09 09:59:39 +00:00
balenaCI
8b047e3b14 v1.10.21 2022-12-09 08:58:01 +00:00
Balena CI
fa41d21e27 Merge pull request #3917 from balena-io/renovate/lint-staged-10.x
Update dependency lint-staged to 10.5.4
2022-12-09 03:56:44 -05:00
Renovate Bot
54e6c5e2c1 Update dependency lint-staged to 10.5.4
Update lint-staged to 10.5.4

Update lint-staged from 10.2.2 to 10.5.4

Change-type: patch
2022-12-09 07:57:13 +00:00
balenaCI
43fc3dd7eb v1.10.20 2022-12-09 06:59:32 +00:00
Balena CI
12a1340c8e Merge pull request #3916 from balena-io/renovate/husky-4.x
Update dependency husky to 4.3.8
2022-12-09 01:58:11 -05:00
Renovate Bot
cf8b5790a1 Update dependency husky to 4.3.8
Update husky to 4.3.8

Update husky from 4.2.5 to 4.3.8

Change-type: patch
2022-12-09 05:56:33 +00:00
balenaCI
659d85a833 v1.10.19 2022-12-09 04:58:50 +00:00
Balena CI
96c44d31c9 Merge pull request #3915 from balena-io/renovate/esbuild-loader-2.x
Update dependency esbuild-loader to 2.20.0
2022-12-08 23:56:57 -05:00
Renovate Bot
ba812b4f64 Update dependency esbuild-loader to 2.20.0
Update esbuild-loader to 2.20.0

Update esbuild-loader from 2.16.0 to 2.20.0

Change-type: patch
2022-12-09 03:59:40 +00:00
balenaCI
4087258fbd v1.10.18 2022-12-09 03:07:59 +00:00
Balena CI
955be13129 Merge pull request #3914 from balena-io/renovate/electron-updater-4.x
Update dependency electron-updater to 4.6.5
2022-12-08 22:06:19 -05:00
Renovate Bot
32011c0dea Update dependency electron-updater to 4.6.5
Update electron-updater to 4.6.5

Update electron-updater from 4.3.5 to 4.6.5

Change-type: patch
2022-12-09 02:21:28 +00:00
balenaCI
b68325c71c v1.10.17 2022-12-09 01:21:27 +00:00
Balena CI
84bce86fce Merge pull request #3913 from balena-io/renovate/electron-notarize-1.x
Update dependency electron-notarize to 1.2.2
2022-12-08 20:19:51 -05:00
Renovate Bot
d68eab1dda Update dependency electron-notarize to 1.2.2
Update electron-notarize to 1.2.2

Update electron-notarize from 1.0.0 to 1.2.2

Change-type: patch
2022-12-08 23:57:37 +00:00
balenaCI
09cf014d14 v1.10.16 2022-12-08 22:58:43 +00:00
Balena CI
d5bab5805f Merge pull request #3912 from balena-io/renovate/awscli-1.x
Update dependency awscli to 1.27.26
2022-12-08 17:57:07 -05:00
Renovate Bot
b5ab500a14 Update dependency awscli to 1.27.26
Update awscli to 1.27.26

Update awscli from 1.27.25 to 1.27.26

Change-type: patch
2022-12-08 21:59:13 +00:00
balenaCI
49253d37c9 v1.10.15 2022-12-08 21:37:02 +00:00
Balena CI
97cf3b25ad Merge pull request #3911 from balena-io/renovate/electron-builder-22.x
Update dependency electron-builder to 22.14.13
2022-12-08 16:35:33 -05:00
Renovate Bot
99862b95a5 Update dependency electron-builder to 22.14.13
Update electron-builder to 22.14.13

Update electron-builder from 22.10.5 to 22.14.13

Change-type: patch
2022-12-08 20:56:08 +00:00
balenaCI
8b765d58e5 v1.10.14 2022-12-08 19:55:07 +00:00
Balena CI
8f566e45b8 Merge pull request #3910 from balena-io/renovate/debug-4.x
Update dependency debug to 4.3.4
2022-12-08 14:53:44 -05:00
Renovate Bot
b8af86e30c Update dependency debug to 4.3.4
Update debug to 4.3.4

Update debug from 4.2.0 to 4.3.4

Change-type: patch
2022-12-08 18:58:28 +00:00
balenaCI
784f193b6d v1.10.13 2022-12-08 17:57:08 +00:00
Balena CI
3967adb1b5 Merge pull request #3909 from balena-io/renovate/awscli-1.x
Update dependency awscli to 1.27.25
2022-12-08 12:55:28 -05:00
Renovate Bot
0667d1110f Update dependency awscli to 1.27.25
Update awscli to 1.27.25

Update awscli from 1.27.24 to 1.27.25

Change-type: patch
2022-12-08 16:59:48 +00:00
balenaCI
61dd22bdf3 v1.10.12 2022-12-08 15:56:15 +00:00
Anton Belodedenko
24eb8b05b0 Merge pull request #3907 from balena-io/renovate/css-loader-5.x
Update dependency css-loader to 5.2.7
2022-12-08 07:54:36 -08:00
Renovate Bot
6991a4950b Update dependency css-loader to 5.2.7
Update css-loader to 5.2.7

Update css-loader from 5.0.1 to 5.2.7

Change-type: patch
2022-12-07 03:55:56 +00:00
balenaCI
bb169cf674 v1.10.11 2022-12-07 03:22:00 +00:00
Anton Belodedenko
e5d0d2e262 Merge pull request #3906 from balena-io/renovate/awscli-1.x
Update dependency awscli to 1.27.24
2022-12-06 19:20:29 -08:00
Renovate Bot
72b4d4f4fa Update dependency awscli to 1.27.24
Update awscli to 1.27.24

Update awscli from 1.27.5 to 1.27.24

Change-type: patch
2022-12-07 02:27:18 +00:00
balenaCI
9b2f2eb4c3 v1.10.10 2022-12-07 02:19:19 +00:00
Anton Belodedenko
ce52ef95a9 Merge pull request #3905 from balena-io/renovate/node-14.x
Update dependency @types/node to 14.18.34
2022-12-06 18:17:44 -08:00
Renovate Bot
aa3756ad17 Update dependency @types/node to 14.18.34
Update @types/node to 14.18.34

Update @types/node from 14.18.33 to 14.18.34

Change-type: patch
2022-12-07 01:17:15 +00:00
balenaCI
73081e726d v1.10.9 2022-12-06 23:59:23 +00:00
Anton Belodedenko
d53dc4149b Merge pull request #3903 from balena-io/ab77/operational
Enable repository configuration
2022-12-06 15:57:58 -08:00
ab77
0d5bb4935f Enable repository configuration
Change-type: patch
2022-12-06 14:59:31 -08:00
balenaCI
14aeb0060b v1.10.8 2022-12-05 21:38:43 +00:00
Anton Belodedenko
239726f3ce Merge pull request #3864 from balena-io/renovate/chai-4.x
Update dependency chai to 4.3.7
2022-12-05 13:37:20 -08:00
Renovate Bot
4ed3002716 Update dependency chai to 4.3.7
Update chai to 4.3.7

Update chai from 4.2.0 to 4.3.7

Change-type: patch
2022-12-05 13:04:10 -08:00
balenaCI
7286fba240 v1.10.7 2022-12-05 19:39:09 +00:00
Anton Belodedenko
895c306fb7 Merge pull request #3868 from balena-io/ab77/operational
Use core workflow for GitHub publish
2022-12-05 11:37:16 -08:00
ab77
f3844d56e2 Use core workflow for GitHub publish
Change-type: patch
2022-12-05 10:51:35 -08:00
balenaCI
540dc3150a v1.10.6 2022-12-02 14:05:00 +00:00
Edwin Joassart
035c8dfec3 Merge pull request #3897 from balena-io/aethernet-assetv
Dummy update to fix asset version issue
2022-12-02 15:03:34 +01:00
Edwin Joassart
03d6a011db Dummy update to fix asset version issue
Due to a race between two patch, 1.10.5 assets are labelled 1.10.3.
This dummy PR should fix this.

Change-type: patch
2022-12-02 14:17:31 +01:00
balenaCI
27f64650f9 v1.10.5 2022-12-02 12:41:21 +00:00
Edwin Joassart
ccca009972 Merge pull request #3893 from balena-io/aethernet-fix-ubuntu
Patch: run linux build on ubuntu-18.04
2022-12-02 13:39:56 +01:00
Edwin Joassart
57a6ceff0e Patch: run linux build on ubuntu-18.04
Running on ubuntu-latest means you need a more recent version of glibc which breaks on older ubuntu.

Thanks to @theofficialgman for suggesting the fix.
2022-12-02 13:00:01 +01:00
balenaCI
30c4baa58b v1.10.4 2022-12-01 23:27:57 +00:00
Anton Belodedenko
a930d77064 Merge pull request #3875 from p-linnane/brew-remove
Remove Homebrew instructions
2022-12-01 15:26:24 -08:00
Patrick Linnane
0d1cfffa5c patch: remove Homebrew instructions in README
Homebrew no longer supports etcher, so removing install instructions.

Change-type: patch
2022-12-01 14:35:59 -08:00
balenaCI
3c7422764c v1.10.3 2022-12-01 22:31:26 +00:00
Anton Belodedenko
55176b9f8f Merge pull request #3895 from balena-io/ab77/external-contributors
Allow external contributors
2022-12-01 14:29:59 -08:00
ab77
156b9314b5 Allow external contributors
Change-type: patch
2022-12-01 13:50:27 -08:00
balenaCI
76d22280dc v1.10.2 2022-11-25 19:22:51 +00:00
bulldozer-balena[bot]
e4251a3862 Merge pull request #3886 from balena-io/aethernet-patch-analytics
Fix missing analytics token
2022-11-25 19:21:35 +00:00
Edwin Joassart
831339bd2c Fix missing analytics token
Change-type: patch
Signed-off-by: Edwin Joassart edwin.joassart@balena.io
2022-11-25 19:14:58 +01:00
balenaCI
952ea80e15 v1.10.1 2022-11-21 16:50:16 +00:00
bulldozer-balena[bot]
813c497e4b Merge pull request #3882 from balena-io/wolvi-lataniere/fix-screensaver-methods-calls
Fixing call to electron block screensaver methods invocation
2022-11-21 16:48:50 +00:00
Aurelien VALADE
1b5b647135 Fixing call to electron block screensaver methods invocation
Replacing `send` calls to `invoke` for `enable/disable-screensaver` calls.

Change-type: patch
Signed-off-by: Aurelien VALADE <aurelien.valade@balena.io>
2022-11-21 16:26:15 +01:00
balenaCI
7de99003ca v1.10.0 2022-11-10 20:54:14 +00:00
bulldozer-balena[bot]
e09bdd734b Merge pull request #3871 from balena-io/test
testing renovate
2022-11-10 20:52:37 +00:00
builder555
306e087ec6 testing renovate
Change-Type: minor
2022-11-10 15:12:39 -05:00
balenaCI
c6b0178a87 v1.9.0 2022-11-08 21:37:26 +00:00
bulldozer-balena[bot]
4e581ea1ce Merge pull request #3861 from balena-io/renovate/awscli-1.x
Update dependency awscli to 1.27.5
2022-11-08 21:36:02 +00:00
Renovate Bot
26dc2d19e5 Update dependency awscli to 1.27.5
Update awscli to 1.27.5

Update awscli from 1.11.87 to 1.27.5

Change-type: minor
2022-11-08 20:50:05 +00:00
balenaCI
b99282acfb v1.8.17 2022-11-08 20:38:29 +00:00
bulldozer-balena[bot]
4e48724d0c Merge pull request #3860 from balena-io/renovate/react-dom-16.x
Update dependency @types/react-dom to 16.9.17
2022-11-08 20:36:50 +00:00
Renovate Bot
448ce141d5 Update dependency @types/react-dom to 16.9.17
Update @types/react-dom to 16.9.17

Update @types/react-dom from 16.8.4 to 16.9.17

Change-type: patch
2022-11-08 19:50:12 +00:00
balenaCI
695f287190 v1.8.16 2022-11-08 19:39:44 +00:00
bulldozer-balena[bot]
4de3271e15 Merge pull request #3858 from balena-io/renovate/react-16.x
Update dependency @types/react to 16.14.34
2022-11-08 19:38:16 +00:00
Renovate Bot
77b33b127d Update dependency @types/react to 16.14.34
Update @types/react to 16.14.34

Update @types/react from 16.8.5 to 16.14.34

Change-type: patch
2022-11-08 18:37:18 +00:00
balenaCI
9cd13ba381 v1.8.15 2022-11-08 18:21:06 +00:00
bulldozer-balena[bot]
9df23c8a3f Merge pull request #3859 from balena-io/ab77/operational
CI: generalise artefact handling
2022-11-08 18:19:29 +00:00
ab77
e3618b939e CI: generalise artefact handling
* on PR syncs, delete draft releases on Linux runners only
* delete draft releases when unmerged PRs are closed

Change-type: patch
2022-11-08 09:41:03 -08:00
balenaCI
6a39f5869a v1.8.14 2022-11-08 13:57:20 +00:00
bulldozer-balena[bot]
fd472efadc Merge pull request #3857 from balena-io/renovate/node-14.x
Update dependency @types/node to 14.18.33
2022-11-08 13:56:11 +00:00
Renovate Bot
7e2c2eae63 Update dependency @types/node to 14.18.33
Update @types/node to 14.18.33

Update @types/node from 14.14.41 to 14.18.33

Change-type: patch
2022-11-08 13:01:36 +00:00
balenaCI
5266571ca4 v1.8.13 2022-11-08 12:39:29 +00:00
bulldozer-balena[bot]
797868c474 Merge pull request #3856 from balena-io/renovate/copy-webpack-plugin-6.x
Update dependency @types/copy-webpack-plugin to 6.4.3
2022-11-08 12:38:11 +00:00
Renovate Bot
2c2a5c7c2b Update dependency @types/copy-webpack-plugin to 6.4.3
Update @types/copy-webpack-plugin to 6.4.3

Update @types/copy-webpack-plugin from 6.0.0 to 6.4.3

Change-type: patch
2022-11-08 11:47:28 +00:00
balenaCI
9e536d5337 v1.8.12 2022-11-08 11:33:03 +00:00
bulldozer-balena[bot]
860e680dd9 Merge pull request #3855 from balena-io/renovate/font-awesome
Update dependency @fortawesome/fontawesome-free to 5.15.4
2022-11-08 11:31:46 +00:00
Renovate Bot
7bb52aa170 Update dependency @fortawesome/fontawesome-free to 5.15.4
Update @fortawesome/fontawesome-free to 5.15.4

Update @fortawesome/fontawesome-free from 5.13.1 to 5.15.4

Change-type: patch
2022-11-08 10:50:37 +00:00
41 changed files with 4492 additions and 3075 deletions

View File

@@ -1,54 +0,0 @@
---
name: publish GitHub release
# https://github.com/product-os/flowzone/tree/master/.github/actions
inputs:
json:
description: "JSON stringified object containing all the inputs from the calling workflow"
required: true
secrets:
description: "JSON stringified object containing all the secrets from the calling workflow"
required: true
runs:
# https://docs.github.com/en/actions/creating-actions/creating-a-composite-action
using: "composite"
steps:
- name: Get release version
if: runner.os == 'Linux'
id: get_release
shell: bash --noprofile --norc -eo pipefail -x {0}
run: |
set -ea
[[ '${{ inputs.VERBOSE }}' =~ on|On|Yes|yes|true|True ]] && set -x
echo "version=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
# https://docs.github.com/en/rest/releases
- name: Finalize GitHub release
if: runner.os == 'Linux'
shell: bash --noprofile --norc -eo pipefail -x {0}
run: |
set -ea
[[ '${{ inputs.VERBOSE }}' =~ on|On|Yes|yes|true|True ]] && set -x
previous_tag="$(git tag --sort=-version:refname | head -n 2 | tail -n 1)"
release_notes="$(git log ${previous_tag}..HEAD --pretty=reference)"
gh release edit '${{ github.event.pull_request.head.ref }}' \
--notes "${release_notes}" \
--title 'v${{ steps.get_release.outputs.version }}' \
--tag 'v${{ steps.get_release.outputs.version }}' \
--prerelease=false \
--draft=false
release_id="$(gh api "/repos/${{ github.repository }}/releases/tags/v${{ steps.get_release.outputs.version }}" \
-H 'Accept: application/vnd.github+json' | jq -r .id)"
gh api --method PATCH "/repos/${{ github.repository }}/releases/${release_id}" \
-H 'Accept: application/vnd.github+json' \
-F make_latest="true"
env:
GITHUB_TOKEN: ${{ fromJSON(inputs.secrets).FLOWZONE_TOKEN }}

View File

@@ -31,17 +31,10 @@ runs:
path: ${{ runner.temp }} path: ${{ runner.temp }}
- name: Extract custom source artifact - name: Extract custom source artifact
if: runner.os != 'Windows' shell: pwsh
shell: bash --noprofile --norc -eo pipefail -x {0}
working-directory: . working-directory: .
run: tar -xf ${{ runner.temp }}/custom.tgz run: tar -xf ${{ runner.temp }}/custom.tgz
- name: Extract custom source artifact
if: runner.os == 'Windows'
shell: powershell
working-directory: .
run: tar -xf ${{ runner.temp }}\custom.tgz
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
@@ -79,10 +72,7 @@ runs:
chmod +x "$(dirname "$(which node)")/resinci-deploy" && which resinci-deploy chmod +x "$(dirname "$(which node)")/resinci-deploy" && which resinci-deploy
fi fi
# FIXME: store sentry workflow is not documented # Upload sourcemaps to sentry
# https://github.com/product-os/resinci-deploy/blob/master/lib/sentry.ts
# https://github.com/getsentry/sentry-cli
# https://docs.sentry.io/api/projects/create-a-new-client-key/
- name: Generate Sentry DSN - name: Generate Sentry DSN
id: sentry id: sentry
shell: bash --noprofile --norc -eo pipefail -x {0} shell: bash --noprofile --norc -eo pipefail -x {0}
@@ -179,6 +169,7 @@ runs:
for target in ${TARGETS}; do for target in ${TARGETS}; do
electron-builder ${ELECTRON_BUILDER_OS} ${target} ${ARCHITECTURE_FLAGS} \ electron-builder ${ELECTRON_BUILDER_OS} ${target} ${ARCHITECTURE_FLAGS} \
--c.extraMetadata.analytics.sentry.token='${{ steps.sentry.outputs.dsn }}' \ --c.extraMetadata.analytics.sentry.token='${{ steps.sentry.outputs.dsn }}' \
--c.extraMetadata.analytics.mixpanel.token='balena-etcher' \
--c.extraMetadata.packageType="${target}" --c.extraMetadata.packageType="${target}"
find dist -type f -maxdepth 1 find dist -type f -maxdepth 1
@@ -212,39 +203,19 @@ runs:
-name "latest*.yml" \ -name "latest*.yml" \
-exec yq -i e .stagingPercentage=\"$percentage\" {} \; -exec yq -i e .stagingPercentage=\"$percentage\" {} \;
# https://github.com/softprops/action-gh-release#-customizing - name: Upload sourcemap to Sentry
- name: Create draft GitHub (pre)release
uses: softprops/action-gh-release@v1
with:
# use PR branch name for draft releases
name: ${{ github.event.pull_request.head.ref }}
tag_name: ${{ github.event.pull_request.head.ref }}
draft: true
prerelease: true
token: ${{ fromJSON(inputs.secrets).FLOWZONE_TOKEN }}
files: |
dist/*.AppImage
dist/*.blockmap
dist/*.deb
dist/*.dmg
dist/*.exe
dist/*.rpm
dist/*.zip
dist/latest*.yml
- name: Compress custom source
if: runner.os != 'Windows'
shell: bash --noprofile --norc -eo pipefail -x {0} shell: bash --noprofile --norc -eo pipefail -x {0}
run: tar -acf ${{ runner.temp }}/custom.tgz . run: |
VERSION=${{ steps.package_release.outputs.version }} npm run uploadSourcemap
env:
SENTRY_AUTH_TOKEN: ${{ fromJSON(inputs.secrets).SENTRY_AUTH_TOKEN }}
npm_config_SENTRY_ORG: balenaEtcher
npm_config_SENTRY_PROJECT: balenaetcher
npm_config_SENTRY_VERSION: ${{ steps.package_release.outputs.version }}
- name: Compress custom source - name: Upload artifacts
if: runner.os == 'Windows'
shell: powershell
run: tar -acf ${{ runner.temp }}\custom.tgz .
- name: Upload custom artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
name: custom-${{ github.event.pull_request.head.sha || github.event.head_commit.id }}-${{ runner.os }} name: gh-release-${{ github.event.pull_request.head.sha || github.event.head_commit.id }}
path: ${{ runner.temp }}/custom.tgz path: dist
retention-days: 1 retention-days: 1

View File

@@ -21,18 +21,6 @@ runs:
# https://docs.github.com/en/actions/creating-actions/creating-a-composite-action # https://docs.github.com/en/actions/creating-actions/creating-a-composite-action
using: "composite" using: "composite"
steps: steps:
- name: Delete previous draft release
shell: bash --noprofile --norc -eo pipefail -x {0}
run: |
set -ea
[[ '${{ inputs.VERBOSE }}' =~ on|On|Yes|yes|true|True ]] && set -x
gh release delete --yes '${{ github.event.pull_request.head.ref }}' || true
env:
GITHUB_TOKEN: ${{ fromJSON(inputs.secrets).FLOWZONE_TOKEN }}
# https://github.com/actions/setup-node#caching-global-packages-data # https://github.com/actions/setup-node#caching-global-packages-data
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
@@ -59,15 +47,9 @@ runs:
ELECTRON_NO_ATTACH_CONSOLE: true ELECTRON_NO_ATTACH_CONSOLE: true
- name: Compress custom source - name: Compress custom source
if: runner.os != 'Windows' shell: pwsh
shell: bash --noprofile --norc -eo pipefail -x {0}
run: tar -acf ${{ runner.temp }}/custom.tgz . run: tar -acf ${{ runner.temp }}/custom.tgz .
- name: Compress custom source
if: runner.os == 'Windows'
shell: powershell
run: tar -acf ${{ runner.temp }}\custom.tgz .
- name: Upload custom artifact - name: Upload custom artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:

View File

@@ -3,14 +3,27 @@ name: Flowzone
on: on:
pull_request: pull_request:
types: [opened, synchronize, closed] types: [opened, synchronize, closed]
branches: branches: [main, master]
- "main" # allow external contributions to use secrets within trusted code
- "master" pull_request_target:
types: [opened, synchronize, closed]
branches: [main, master]
jobs: jobs:
flowzone: flowzone:
name: Flowzone name: Flowzone
uses: product-os/flowzone/.github/workflows/flowzone.yml@master uses: product-os/flowzone/.github/workflows/flowzone.yml@master
# prevent duplicate workflows and only allow one `pull_request` or `pull_request_target` for
# internal or external contributions respectively
if: |
(github.event.pull_request.head.repo.full_name == github.repository && github.event_name == 'pull_request') ||
(github.event.pull_request.head.repo.full_name != github.repository && github.event_name == 'pull_request_target')
secrets: inherit secrets: inherit
with: with:
tests_run_on: '["ubuntu-latest","macos-latest","windows-2019"]' tests_run_on: '["ubuntu-20.04","macos-latest","windows-2019"]'
restrict_custom_actions: false
github_prerelease: true
repo_config: true
repo_description: "Flash OS images to SD cards & USB drives, safely and easily."
repo_homepage: https://etcher.io/
repo_enable_wiki: true

13
.github/workflows/winget.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
name: Publish to WinGet
on:
release:
types: [released]
jobs:
publish:
runs-on: windows-latest # action can only be run on windows
steps:
- uses: vedantmgoyal2009/winget-releaser@v1
with:
identifier: Balena.Etcher
installers-regex: 'balenaEtcher-Setup.*.exe$'
token: ${{ secrets.WINGET_PAT }}

View File

@@ -1,3 +1,942 @@
- commits:
- subject: Adding EtcherPro device serial number to the Settings modal
hash: d25eda9a7d6bf89284b630b2d55cbb0a7e3a9432
body: ""
footer:
Change-type: patch
change-type: patch
author: Aurelien VALADE
nested: []
version: 1.13.4
title: ""
date: 2023-01-12T15:10:50.328Z
- commits:
- subject: "patch: progress cm4 to second stage"
hash: 2475d576c7d9ecb46507c47c4143bdbfbdb44e45
body: ""
footer: {}
author: Peter Makra
nested: []
version: 1.13.3
title: ""
date: 2023-01-11T14:30:45.116Z
- commits:
- subject: "patch: fixed winget parameter name"
hash: 33fe4b2c1abcb7f71f42a4b682f174422cb72a00
body: ""
footer: {}
author: mcraa
nested: []
version: 1.13.2
title: ""
date: 2023-01-02T20:55:58.179Z
- commits:
- subject: "patch: updated sdk to fix bz2 issue"
hash: f79cb0fac56f6ec86f3a6f9be7035fbf59102253
body: ""
footer: {}
author: Peter Makra
nested: []
- subject: "patch: update copyright in electron-builder"
hash: ec42892c7cf1d22f4bb2968733ba9dc85e3552c6
body: ""
footer: {}
author: JOASSART Edwin
nested: []
version: 1.13.1
title: ""
date: 2023-01-02T17:26:55.602Z
- commits:
- subject: "minor: electron version bump"
hash: e3072ac416470cd161309935c2622cc5a3d8d242
body: ""
footer: {}
author: Peter Makra
nested: []
- subject: "patch: handle ext2fs with webpack"
hash: b59b171e43a170c0ccf84d36ab4ba2db403e25c5
body: ""
footer: {}
author: Peter Makra
nested: []
- subject: "Patch: update etcher-sdk version to fix CM4 issues"
hash: 36c813714b3ce60e5e85f1889c9bc7eeadb524b4
body: ""
footer:
Change-type: patch
change-type: patch
author: builder555
nested: []
version: 1.13.0
title: ""
date: 2022-12-28T16:48:12.506Z
- commits:
- subject: Update dependency i18next to 21.10.0
hash: b068b847c7ae6456ebd16a5d641ff61d8d074015
body: |
Update i18next to 21.10.0
Update i18next from 21.8.14 to 21.10.0
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.12.7
title: ""
date: 2022-12-20T19:35:11.219Z
- commits:
- subject: Update dependency react-i18next to 11.18.6
hash: 2e85fb45de3a52e9bf0605e474a550e1af2bb980
body: |
Update react-i18next to 11.18.6
Update react-i18next from 11.18.1 to 11.18.6
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.12.6
title: ""
date: 2022-12-20T18:00:03.165Z
- commits:
- subject: "Patch: made trim setting more readable"
hash: 5c5a7612220b011e6942ac10b7026b7d6513e54f
body: ""
footer:
Change-type: patch
change-type: patch
author: builder555
nested: []
version: 1.12.5
title: ""
date: 2022-12-20T12:27:33.706Z
- commits:
- subject: "patch: publish to winget with gh action"
hash: f9c8378d6a96e1c44d0bced0d3227a9930b9fd14
body: ""
footer: {}
author: Begula
nested: []
version: 1.12.4
title: ""
date: 2022-12-19T19:41:59.151Z
- commits:
- subject: "Patch: replaced plain text with i18n in settings"
hash: 11cea7c926be1bac27df8ab583cbb4b8752a49c5
body: ""
footer:
Change-type: patch
change-type: patch
author: builder555
nested: []
version: 1.12.3
title: ""
date: 2022-12-19T09:51:52.545Z
- commits:
- subject: Update dependency webpack-dev-server to 4.11.1
hash: c9e9d7d109ee103402acea1c7be4bac2f674168a
body: |
Update webpack-dev-server to 4.11.1
Update webpack-dev-server from 4.5.0 to 4.11.1
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.12.2
title: ""
date: 2022-12-16T16:59:03.254Z
- commits:
- subject: "Patch: expose trim ext{2,3,4} setting"
hash: b9a82be29bee61a41f6f6a5ca6043dd8a7bee547
body: ""
footer:
Change-type: patch
change-type: patch
author: builder555
nested: []
version: 1.12.1
title: ""
date: 2022-12-16T15:02:34.104Z
- commits:
- subject: i18n support and Chinese translation
hash: 8fc574f0596f256382523c3b269e647a9aed5747
body: ""
footer:
Change-type: minor
change-type: minor
author: ab77
nested: []
- subject: "minor: optimize i18n"
hash: 67d26ff7902c272e8113c9b650382a1dcb0cdde0
body: >
Optimized several translations.
This commit itself is only a patch, but as a pull request must have at least one commit with a change-type.
footer:
Change-Type: minor
change-type: minor
author: r-q
nested: []
version: 1.12.0
title: ""
date: 2022-12-14T16:17:31.131Z
- commits:
- subject: Update dependency webpack-cli to 4.10.0
hash: 757aa77d897d6266afbf6e7d62ddd0255ea0c926
body: |
Update webpack-cli to 4.10.0
Update webpack-cli from 4.2.0 to 4.10.0
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.11.10
title: ""
date: 2022-12-13T02:27:41.593Z
- commits:
- subject: Update dependency webpack to 5.75.0
hash: cd67b442c9c55adddb2d8def456d7155af1f23c6
body: |
Update webpack to 5.75.0
Update webpack from 5.11.0 to 5.75.0
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.11.9
title: ""
date: 2022-12-12T23:58:09.807Z
- commits:
- subject: Update dependency awscli to 1.27.28
hash: 927a026b869e0da872e17a662536d0ad3aeeae0f
body: |
Update awscli to 1.27.28
Update awscli from 1.27.27 to 1.27.28
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.11.8
title: ""
date: 2022-12-12T21:55:28.620Z
- commits:
- subject: Update dependency uuid to 8.3.2
hash: c9cfb87733a694a69044a3b04cb12e72047a92da
body: |
Update uuid to 8.3.2
Update uuid from 8.1.0 to 8.3.2
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.11.7
title: ""
date: 2022-12-12T19:57:31.379Z
- commits:
- subject: Update dependency tslib to 2.4.1
hash: f0747abe3fde8df4a004573a3ffd49134dd6d40d
body: |
Update tslib to 2.4.1
Update tslib from 2.0.0 to 2.4.1
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
- subject: "Patch: run linux build on ubuntu-20.04"
hash: adcd8e0325bc891460b3e51aa5403f8675189f13
body: >-
as [`18.04` has been
removed](https://github.blog/changelog/2022-08-09-github-actions-the-ubuntu-18-04-actions-runner-image-is-being-deprecated-and-will-be-removed-by-12-1-22/)
We cannot use `latest` as the glibc version will cause issue with older ubuntu version.
footer: {}
author: Edwin Joassart
nested: []
version: 1.11.6
title: ""
date: 2022-12-12T17:59:43.391Z
- commits:
- subject: Update dependency ts-loader to 8.4.0
hash: 5ae9a263619e9bb499705ee7c19df5707ea3936c
body: |
Update ts-loader to 8.4.0
Update ts-loader from 8.0.12 to 8.4.0
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.11.5
title: ""
date: 2022-12-10T12:28:18.918Z
- commits:
- subject: Update dependency styled-components to 5.3.6
hash: 88c5fa50352efe76a6506ee763915f504889111b
body: |
Update styled-components to 5.3.6
Update styled-components from 5.1.0 to 5.3.6
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.11.4
title: ""
date: 2022-12-10T10:57:10.809Z
- commits:
- subject: Update dependency terser-webpack-plugin to 5.3.6
hash: c431222909ef49126549c0f630cf1f3f3f8895ed
body: |
Update terser-webpack-plugin to 5.3.6
Update terser-webpack-plugin from 5.2.5 to 5.3.6
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.11.3
title: ""
date: 2022-12-10T08:54:53.274Z
- commits:
- subject: Update dependency string-replace-loader to 3.1.0
hash: 33f8851083d50ed2db2b1308d1f1cf8749751db5
body: |
Update string-replace-loader to 3.1.0
Update string-replace-loader from 3.0.1 to 3.1.0
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.11.2
title: ""
date: 2022-12-10T07:32:25.553Z
- commits:
- subject: Update dependency sinon to 9.2.4
hash: 686a5837b69c26bc83772ed738376ce0a766fef5
body: |
Update sinon to 9.2.4
Update sinon from 9.0.2 to 9.2.4
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.11.1
title: ""
date: 2022-12-10T06:19:30.932Z
- commits:
- subject: Update dependency shyaml to 0.6.2
hash: 2acad790d3e85b3215e692705691fff4fadb99b0
body: |
Update shyaml to 0.6.2
Update shyaml from 0.5.0 to 0.6.2
footer:
Change-type: minor
change-type: minor
author: Renovate Bot
nested: []
version: 1.11.0
title: ""
date: 2022-12-10T04:27:19.119Z
- commits:
- subject: Update dependency awscli to 1.27.27
hash: 17858a7d72dc001419bf75ac04b1a66b782404e2
body: |
Update awscli to 1.27.27
Update awscli from 1.27.26 to 1.27.27
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.29
title: ""
date: 2022-12-10T03:05:02.826Z
- commits:
- subject: Update dependency rendition to 19.3.2
hash: 0d740ad12dbadcb35d0e2076821a073177476acb
body: |
Update rendition to 19.3.2
Update rendition from 19.2.0 to 19.3.2
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested:
- commits:
- subject: Add Breadcrumbs component export
hash: fbe0da641ae76ed99185f5799f94653bbed52609
body: |
add breadcrumbs component export
footer:
Change-type: patch
change-type: patch
Signed-off-by: Andrea Rosci <andrear@balena.io>
signed-off-by: Andrea Rosci <andrear@balena.io>
author: JSReds
version: rendition-19.3.2
date: 2020-12-29T17:27:09.528Z
- commits:
- subject: Fix max-width on breadcrumbs container
hash: b7c4ab7bed3caa1c10130f50abb582fcf63d867e
body: |
fix max-width on breadcrumbs container
footer:
Change-type: patch
change-type: patch
Signed-off-by: Andrea Rosci <andrear@balena.io>
signed-off-by: Andrea Rosci <andrear@balena.io>
author: JSReds
version: rendition-19.3.1
date: 2020-12-29T13:35:01.615Z
- commits:
- subject: Add Breadcrumbs component
hash: 41a7abb3724a6c8a0a839d4083ce36ceaeeb9d91
body: |
Add Breadcrumbs component and generate snapshots
footer:
Change-type: minor
change-type: minor
Signed-off-by: Andrea Rosci <andrear@balena.io>
signed-off-by: Andrea Rosci <andrear@balena.io>
author: JSReds
version: rendition-19.3.0
date: 2020-12-29T12:12:16.944Z
version: 1.10.28
title: ""
date: 2022-12-10T02:10:41.368Z
- commits:
- subject: Update dependency redux to 4.2.0
hash: 85c183b9ef2dbe798c6d5cd8bce6367ef31e2624
body: |
Update redux to 4.2.0
Update redux from 4.0.5 to 4.2.0
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.27
title: ""
date: 2022-12-09T20:59:24.075Z
- commits:
- subject: Update dependency pretty-bytes to 5.6.0
hash: d8b2a7a2369f24b1390bd85eca3cfbcd8282df80
body: |
Update pretty-bytes to 5.6.0
Update pretty-bytes from 5.3.0 to 5.6.0
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.26
title: ""
date: 2022-12-09T18:58:21.970Z
- commits:
- subject: Update dependency pnp-webpack-plugin to 1.7.0
hash: 86bb093f3d7eec4835060789cc725e172223c74f
body: |
Update pnp-webpack-plugin to 1.7.0
Update pnp-webpack-plugin from 1.6.4 to 1.7.0
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.25
title: ""
date: 2022-12-09T17:01:52.897Z
- commits:
- subject: Update dependency node-ipc to 9.2.1
hash: f26b0748114c7623f152e00b065f3e6ec0657e83
body: |
Update node-ipc to 9.2.1
Update node-ipc from 9.1.1 to 9.2.1
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.24
title: ""
date: 2022-12-09T14:59:54.907Z
- commits:
- subject: Update dependency mocha to 8.4.0
hash: be190c6c802f0cb6f5f68981b255aa4e620db2f7
body: |
Update mocha to 8.4.0
Update mocha from 8.0.1 to 8.4.0
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.23
title: ""
date: 2022-12-09T13:05:52.859Z
- commits:
- subject: Update dependency mini-css-extract-plugin to 1.6.2
hash: d35f3c30498e3a8d8b8eb74a50952489f1c629fc
body: |
Update mini-css-extract-plugin to 1.6.2
Update mini-css-extract-plugin from 1.3.3 to 1.6.2
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.22
title: ""
date: 2022-12-09T10:57:43.780Z
- commits:
- subject: Update dependency lint-staged to 10.5.4
hash: 54e6c5e2c137073e6229fa28726d8f6b08853fcc
body: |
Update lint-staged to 10.5.4
Update lint-staged from 10.2.2 to 10.5.4
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.21
title: ""
date: 2022-12-09T08:57:59.766Z
- commits:
- subject: Update dependency husky to 4.3.8
hash: cf8b5790a1e9cf853328f128f9c52d72d5ac1da5
body: |
Update husky to 4.3.8
Update husky from 4.2.5 to 4.3.8
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.20
title: ""
date: 2022-12-09T06:59:31.264Z
- commits:
- subject: Update dependency esbuild-loader to 2.20.0
hash: ba812b4f6484f0803486f7c1969992030267ae12
body: |
Update esbuild-loader to 2.20.0
Update esbuild-loader from 2.16.0 to 2.20.0
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.19
title: ""
date: 2022-12-09T04:58:48.480Z
- commits:
- subject: Update dependency electron-updater to 4.6.5
hash: 32011c0deab646af1c4d99c15418f336f1dc02f1
body: |
Update electron-updater to 4.6.5
Update electron-updater from 4.3.5 to 4.6.5
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.18
title: ""
date: 2022-12-09T03:07:57.710Z
- commits:
- subject: Update dependency electron-notarize to 1.2.2
hash: d68eab1dda78e17ce3804e6c7f08940b36f377a8
body: |
Update electron-notarize to 1.2.2
Update electron-notarize from 1.0.0 to 1.2.2
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.17
title: ""
date: 2022-12-09T01:21:25.322Z
- commits:
- subject: Update dependency awscli to 1.27.26
hash: b5ab500a14396525cb6c7bac4eabf0b4b1c7cb11
body: |
Update awscli to 1.27.26
Update awscli from 1.27.25 to 1.27.26
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.16
title: ""
date: 2022-12-08T22:58:41.740Z
- commits:
- subject: Update dependency electron-builder to 22.14.13
hash: 99862b95a55a3a7a174763d635073bab5dbc704f
body: |
Update electron-builder to 22.14.13
Update electron-builder from 22.10.5 to 22.14.13
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.15
title: ""
date: 2022-12-08T21:37:01.110Z
- commits:
- subject: Update dependency debug to 4.3.4
hash: b8af86e30c9ce3b8d9eba8749f2aeba1f6eea197
body: |
Update debug to 4.3.4
Update debug from 4.2.0 to 4.3.4
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.14
title: ""
date: 2022-12-08T19:55:06.173Z
- commits:
- subject: Update dependency awscli to 1.27.25
hash: 0667d1110fbc05ef7222530ea413a1db7a2bd814
body: |
Update awscli to 1.27.25
Update awscli from 1.27.24 to 1.27.25
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.13
title: ""
date: 2022-12-08T17:57:06.474Z
- commits:
- subject: Update dependency css-loader to 5.2.7
hash: 6991a4950bfb2b7c9ad93df4c76170003b7d47f0
body: |
Update css-loader to 5.2.7
Update css-loader from 5.0.1 to 5.2.7
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.12
title: ""
date: 2022-12-08T15:56:12.526Z
- commits:
- subject: Update dependency awscli to 1.27.24
hash: 72b4d4f4fa5a013d9a808402660186a92b165bc7
body: |
Update awscli to 1.27.24
Update awscli from 1.27.5 to 1.27.24
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.11
title: ""
date: 2022-12-07T03:21:58.354Z
- commits:
- subject: Update dependency @types/node to 14.18.34
hash: aa3756ad172e939dff88ad213fda2b57966341c6
body: |
Update @types/node to 14.18.34
Update @types/node from 14.18.33 to 14.18.34
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.10
title: ""
date: 2022-12-07T02:19:17.414Z
- commits:
- subject: Enable repository configuration
hash: 0d5bb4935f860a5b7f58810fce8084dc8f82dd65
body: ""
footer:
Change-type: patch
change-type: patch
author: ab77
nested: []
version: 1.10.9
title: ""
date: 2022-12-06T23:59:21.301Z
- commits:
- subject: Update dependency chai to 4.3.7
hash: 4ed30027162365a68f26264f7574ac9eaf752926
body: |
Update chai to 4.3.7
Update chai from 4.2.0 to 4.3.7
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.10.8
title: ""
date: 2022-12-05T21:38:41.964Z
- commits:
- subject: Use core workflow for GitHub publish
hash: f3844d56e2bb317e9360f34f5054c91eb0fb8910
body: ""
footer:
Change-type: patch
change-type: patch
author: ab77
nested: []
version: 1.10.7
title: ""
date: 2022-12-05T19:39:07.247Z
- commits:
- subject: Dummy update to fix asset version issue
hash: 03d6a011db5fd4dad3d25fde86cf2b434c8192e8
body: |
Due to a race between two patch, 1.10.5 assets are labelled 1.10.3.
This dummy PR should fix this.
footer:
Change-type: patch
change-type: patch
author: Edwin Joassart
nested: []
version: 1.10.6
title: ""
date: 2022-12-02T14:04:57.766Z
- commits:
- subject: "Patch: run linux build on ubuntu-18.04"
hash: 57a6ceff0e28d06063679a7a8b14671416ba46c5
body: >-
Running on ubuntu-latest means you need a more recent version of glibc
which breaks on older ubuntu.
Thanks to @theofficialgman for suggesting the fix.
footer: {}
author: Edwin Joassart
nested: []
version: 1.10.5
title: ""
date: 2022-12-02T12:41:19.841Z
- commits:
- subject: "patch: remove Homebrew instructions in README"
hash: 0d1cfffa5c7c084d9f48d60c1abbf7e2974abb28
body: |
Homebrew no longer supports etcher, so removing install instructions.
footer:
Change-type: patch
change-type: patch
author: Patrick Linnane
nested: []
version: 1.10.4
title: ""
date: 2022-12-01T23:27:55.910Z
- commits:
- subject: Allow external contributors
hash: 156b9314b5786e943256974d5344383ae1f0650d
body: ""
footer:
Change-type: patch
change-type: patch
author: ab77
nested: []
version: 1.10.3
title: ""
date: 2022-12-01T22:31:25.592Z
- commits:
- subject: Fix missing analytics token
hash: 831339bd2cbe73dd441cdd77d85b34e98f68a6a6
body: ""
footer:
Change-type: patch
change-type: patch
Signed-off-by: Edwin Joassart edwin.joassart@balena.io
signed-off-by: Edwin Joassart edwin.joassart@balena.io
author: Edwin Joassart
nested: []
version: 1.10.2
title: ""
date: 2022-11-25T19:22:49.679Z
- commits:
- subject: Fixing call to electron block screensaver methods invocation
hash: 1b5b64713505dfb69448bc2184839b4c23bd677b
body: >
Replacing `send` calls to `invoke` for `enable/disable-screensaver` calls.
footer:
Change-type: patch
change-type: patch
Signed-off-by: Aurelien VALADE <aurelien.valade@balena.io>
signed-off-by: Aurelien VALADE <aurelien.valade@balena.io>
author: Aurelien VALADE
nested: []
version: 1.10.1
title: ""
date: 2022-11-21T16:50:14.797Z
- commits:
- subject: testing renovate
hash: 306e087ec6daed9e736a8918cde07159dd9298dc
body: ""
footer:
Change-Type: minor
change-type: minor
author: builder555
nested: []
version: 1.10.0
title: ""
date: 2022-11-10T20:54:12.345Z
- commits:
- subject: Update dependency awscli to 1.27.5
hash: 26dc2d19e56354b0f43c9af2f1d6dd51a4a0b235
body: |
Update awscli to 1.27.5
Update awscli from 1.11.87 to 1.27.5
footer:
Change-type: minor
change-type: minor
author: Renovate Bot
nested: []
version: 1.9.0
title: ""
date: 2022-11-08T21:37:25.500Z
- commits:
- subject: Update dependency @types/react-dom to 16.9.17
hash: 448ce141d51ec342e95148f265daf0fc73df694c
body: |
Update @types/react-dom to 16.9.17
Update @types/react-dom from 16.8.4 to 16.9.17
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.8.17
title: ""
date: 2022-11-08T20:38:27.629Z
- commits:
- subject: Update dependency @types/react to 16.14.34
hash: 77b33b127dcfb0345e0ff80c80b2f560984c14b1
body: |
Update @types/react to 16.14.34
Update @types/react from 16.8.5 to 16.14.34
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.8.16
title: ""
date: 2022-11-08T19:39:42.616Z
- commits:
- subject: "CI: generalise artefact handling"
hash: e3618b939e119b8ae6d0dcea0f4077fe2c332122
body: |
* on PR syncs, delete draft releases on Linux runners only
* delete draft releases when unmerged PRs are closed
footer:
Change-type: patch
change-type: patch
author: ab77
nested: []
version: 1.8.15
title: ""
date: 2022-11-08T18:21:04.227Z
- commits:
- subject: Update dependency @types/node to 14.18.33
hash: 7e2c2eae635e6d9aef1e65b158268400074ff020
body: |
Update @types/node to 14.18.33
Update @types/node from 14.14.41 to 14.18.33
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.8.14
title: ""
date: 2022-11-08T13:57:18.149Z
- commits:
- subject: Update dependency @types/copy-webpack-plugin to 6.4.3
hash: 2c2a5c7c2b31d188cc32024dd6f9b5d0d1a5bc8b
body: |
Update @types/copy-webpack-plugin to 6.4.3
Update @types/copy-webpack-plugin from 6.0.0 to 6.4.3
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.8.13
title: ""
date: 2022-11-08T12:39:27.293Z
- commits:
- subject: Update dependency @fortawesome/fontawesome-free to 5.15.4
hash: 7bb52aa1706b4bfe06cdd023f4f95bf8de1a6666
body: |
Update @fortawesome/fontawesome-free to 5.15.4
Update @fortawesome/fontawesome-free from 5.13.1 to 5.15.4
footer:
Change-type: patch
change-type: patch
author: Renovate Bot
nested: []
version: 1.8.12
title: ""
date: 2022-11-08T11:33:01.286Z
- commits: - commits:
- subject: Update dependency @balena/lint to 5.4.2 - subject: Update dependency @balena/lint to 5.4.2
hash: cc0285a77db78a014b73169cc8a6b2429961f41f hash: cc0285a77db78a014b73169cc8a6b2429961f41f

View File

@@ -3,6 +3,336 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/). This project adheres to [Semantic Versioning](http://semver.org/).
# v1.13.4
## (2023-01-12)
* Adding EtcherPro device serial number to the Settings modal [Aurelien VALADE]
# v1.13.3
## (2023-01-11)
* patch: progress cm4 to second stage [Peter Makra]
# v1.13.2
## (2023-01-02)
* patch: fixed winget parameter name [mcraa]
# v1.13.1
## (2023-01-02)
* patch: updated sdk to fix bz2 issue [Peter Makra]
* patch: update copyright in electron-builder [JOASSART Edwin]
# v1.13.0
## (2022-12-28)
* minor: electron version bump [Peter Makra]
* patch: handle ext2fs with webpack [Peter Makra]
* Patch: update etcher-sdk version to fix CM4 issues [builder555]
# v1.12.7
## (2022-12-20)
* Update dependency i18next to 21.10.0 [Renovate Bot]
# v1.12.6
## (2022-12-20)
* Update dependency react-i18next to 11.18.6 [Renovate Bot]
# v1.12.5
## (2022-12-20)
* Patch: made trim setting more readable [builder555]
# v1.12.4
## (2022-12-19)
* patch: publish to winget with gh action [Begula]
# v1.12.3
## (2022-12-19)
* Patch: replaced plain text with i18n in settings [builder555]
# v1.12.2
## (2022-12-16)
* Update dependency webpack-dev-server to 4.11.1 [Renovate Bot]
# v1.12.1
## (2022-12-16)
* Patch: expose trim ext{2,3,4} setting [builder555]
# v1.12.0
## (2022-12-14)
* i18n support and Chinese translation [ab77]
* minor: optimize i18n [r-q]
# v1.11.10
## (2022-12-13)
* Update dependency webpack-cli to 4.10.0 [Renovate Bot]
# v1.11.9
## (2022-12-12)
* Update dependency webpack to 5.75.0 [Renovate Bot]
# v1.11.8
## (2022-12-12)
* Update dependency awscli to 1.27.28 [Renovate Bot]
# v1.11.7
## (2022-12-12)
* Update dependency uuid to 8.3.2 [Renovate Bot]
# v1.11.6
## (2022-12-12)
* Update dependency tslib to 2.4.1 [Renovate Bot]
* Patch: run linux build on ubuntu-20.04 [Edwin Joassart]
# v1.11.5
## (2022-12-10)
* Update dependency ts-loader to 8.4.0 [Renovate Bot]
# v1.11.4
## (2022-12-10)
* Update dependency styled-components to 5.3.6 [Renovate Bot]
# v1.11.3
## (2022-12-10)
* Update dependency terser-webpack-plugin to 5.3.6 [Renovate Bot]
# v1.11.2
## (2022-12-10)
* Update dependency string-replace-loader to 3.1.0 [Renovate Bot]
# v1.11.1
## (2022-12-10)
* Update dependency sinon to 9.2.4 [Renovate Bot]
# v1.11.0
## (2022-12-10)
* Update dependency shyaml to 0.6.2 [Renovate Bot]
# v1.10.29
## (2022-12-10)
* Update dependency awscli to 1.27.27 [Renovate Bot]
# v1.10.28
## (2022-12-10)
<details>
<summary> Update dependency rendition to 19.3.2 [Renovate Bot] </summary>
> ## rendition-19.3.2
> ### (2020-12-29)
>
> * Add Breadcrumbs component export [JSReds]
>
> ## rendition-19.3.1
> ### (2020-12-29)
>
> * Fix max-width on breadcrumbs container [JSReds]
>
> ## rendition-19.3.0
> ### (2020-12-29)
>
> * Add Breadcrumbs component [JSReds]
>
</details>
# v1.10.27
## (2022-12-09)
* Update dependency redux to 4.2.0 [Renovate Bot]
# v1.10.26
## (2022-12-09)
* Update dependency pretty-bytes to 5.6.0 [Renovate Bot]
# v1.10.25
## (2022-12-09)
* Update dependency pnp-webpack-plugin to 1.7.0 [Renovate Bot]
# v1.10.24
## (2022-12-09)
* Update dependency node-ipc to 9.2.1 [Renovate Bot]
# v1.10.23
## (2022-12-09)
* Update dependency mocha to 8.4.0 [Renovate Bot]
# v1.10.22
## (2022-12-09)
* Update dependency mini-css-extract-plugin to 1.6.2 [Renovate Bot]
# v1.10.21
## (2022-12-09)
* Update dependency lint-staged to 10.5.4 [Renovate Bot]
# v1.10.20
## (2022-12-09)
* Update dependency husky to 4.3.8 [Renovate Bot]
# v1.10.19
## (2022-12-09)
* Update dependency esbuild-loader to 2.20.0 [Renovate Bot]
# v1.10.18
## (2022-12-09)
* Update dependency electron-updater to 4.6.5 [Renovate Bot]
# v1.10.17
## (2022-12-09)
* Update dependency electron-notarize to 1.2.2 [Renovate Bot]
# v1.10.16
## (2022-12-08)
* Update dependency awscli to 1.27.26 [Renovate Bot]
# v1.10.15
## (2022-12-08)
* Update dependency electron-builder to 22.14.13 [Renovate Bot]
# v1.10.14
## (2022-12-08)
* Update dependency debug to 4.3.4 [Renovate Bot]
# v1.10.13
## (2022-12-08)
* Update dependency awscli to 1.27.25 [Renovate Bot]
# v1.10.12
## (2022-12-08)
* Update dependency css-loader to 5.2.7 [Renovate Bot]
# v1.10.11
## (2022-12-07)
* Update dependency awscli to 1.27.24 [Renovate Bot]
# v1.10.10
## (2022-12-07)
* Update dependency @types/node to 14.18.34 [Renovate Bot]
# v1.10.9
## (2022-12-06)
* Enable repository configuration [ab77]
# v1.10.8
## (2022-12-05)
* Update dependency chai to 4.3.7 [Renovate Bot]
# v1.10.7
## (2022-12-05)
* Use core workflow for GitHub publish [ab77]
# v1.10.6
## (2022-12-02)
* Dummy update to fix asset version issue [Edwin Joassart]
# v1.10.5
## (2022-12-02)
* Patch: run linux build on ubuntu-18.04 [Edwin Joassart]
# v1.10.4
## (2022-12-01)
* patch: remove Homebrew instructions in README [Patrick Linnane]
# v1.10.3
## (2022-12-01)
* Allow external contributors [ab77]
# v1.10.2
## (2022-11-25)
* Fix missing analytics token [Edwin Joassart]
# v1.10.1
## (2022-11-21)
* Fixing call to electron block screensaver methods invocation [Aurelien VALADE]
# v1.10.0
## (2022-11-10)
* testing renovate [builder555]
# v1.9.0
## (2022-11-08)
* Update dependency awscli to 1.27.5 [Renovate Bot]
# v1.8.17
## (2022-11-08)
* Update dependency @types/react-dom to 16.9.17 [Renovate Bot]
# v1.8.16
## (2022-11-08)
* Update dependency @types/react to 16.14.34 [Renovate Bot]
# v1.8.15
## (2022-11-08)
* CI: generalise artefact handling [ab77]
# v1.8.14
## (2022-11-08)
* Update dependency @types/node to 14.18.33 [Renovate Bot]
# v1.8.13
## (2022-11-08)
* Update dependency @types/copy-webpack-plugin to 6.4.3 [Renovate Bot]
# v1.8.12
## (2022-11-08)
* Update dependency @fortawesome/fontawesome-free to 5.15.4 [Renovate Bot]
# v1.8.11 # v1.8.11
## (2022-11-08) ## (2022-11-08)

View File

@@ -170,22 +170,6 @@ yay -S balena-etcher
yay -R balena-etcher yay -R balena-etcher
``` ```
#### Brew (macOS)
**Note**: Etcher has to be updated manually to point to new versions,
so it might not refer to the latest version immediately after an Etcher
release.
```sh
brew install balenaetcher
```
##### Uninstall
```sh
brew uninstall balenaetcher
```
#### Chocolatey (Windows) #### Chocolatey (Windows)
This package is maintained by [@majkinetor](https://github.com/majkinetor), and This package is maintained by [@majkinetor](https://github.com/majkinetor), and
@@ -220,3 +204,5 @@ the [license].
[milestones]: https://github.com/balena-io/etcher/milestones [milestones]: https://github.com/balena-io/etcher/milestones
[newissue]: https://github.com/balena-io/etcher/issues/new [newissue]: https://github.com/balena-io/etcher/issues/new
[license]: https://github.com/balena-io/etcher/blob/master/LICENSE [license]: https://github.com/balena-io/etcher/blob/master/LICENSE

View File

@@ -1,13 +1,14 @@
# https://www.electron.build/configuration/configuration # https://www.electron.build/configuration/configuration
appId: io.balena.etcher appId: io.balena.etcher
copyright: Copyright 2016-2021 Balena Ltd copyright: Copyright 2016-2023 Balena Ltd
productName: balenaEtcher productName: balenaEtcher
afterPack: ./afterPack.js afterPack: ./afterPack.js
afterSign: ./afterSignHook.js afterSign: ./afterSignHook.js
asar: false asar: false
files: files:
- generated - generated
- lib/shared/catalina-sudo/sudo-askpass.osascript.js - lib/shared/catalina-sudo/sudo-askpass.osascript-zh.js
- lib/shared/catalina-sudo/sudo-askpass.osascript-en.js
mac: mac:
icon: assets/icon.icns icon: assets/icon.icns
category: public.app-category.developer-tools category: public.app-category.developer-tools

View File

@@ -38,6 +38,7 @@ import * as osDialog from './os/dialog';
import * as windowProgress from './os/window-progress'; import * as windowProgress from './os/window-progress';
import MainPage from './pages/main/MainPage'; import MainPage from './pages/main/MainPage';
import './css/main.css'; import './css/main.css';
import * as i18next from 'i18next';
window.addEventListener( window.addEventListener(
'unhandledrejection', 'unhandledrejection',
@@ -313,9 +314,9 @@ window.addEventListener('beforeunload', async (event) => {
try { try {
const confirmed = await osDialog.showWarning({ const confirmed = await osDialog.showWarning({
confirmationLabel: 'Yes, quit', confirmationLabel: i18next.t('yesExit'),
rejectionLabel: 'Cancel', rejectionLabel: i18next.t('cancel'),
title: 'Are you sure you want to close Etcher?', title: i18next.t('reallyExit'),
description: messages.warning.exitWhileFlashing(), description: messages.warning.exitWhileFlashing(),
}); });
if (confirmed) { if (confirmed) {

View File

@@ -44,6 +44,7 @@ import {
import { SourceMetadata } from '../source-selector/source-selector'; import { SourceMetadata } from '../source-selector/source-selector';
import { middleEllipsis } from '../../utils/middle-ellipsis'; import { middleEllipsis } from '../../utils/middle-ellipsis';
import * as i18next from 'i18next';
interface UsbbootDrive extends sourceDestination.UsbbootDrive { interface UsbbootDrive extends sourceDestination.UsbbootDrive {
progress: number; progress: number;
@@ -189,7 +190,7 @@ export class DriveSelector extends React.Component<
this.tableColumns = [ this.tableColumns = [
{ {
field: 'description', field: 'description',
label: 'Name', label: i18next.t('drives.name'),
render: (description: string, drive: Drive) => { render: (description: string, drive: Drive) => {
if (isDrivelistDrive(drive)) { if (isDrivelistDrive(drive)) {
const isLargeDrive = isDriveSizeLarge(drive); const isLargeDrive = isDriveSizeLarge(drive);
@@ -215,7 +216,7 @@ export class DriveSelector extends React.Component<
{ {
field: 'description', field: 'description',
key: 'size', key: 'size',
label: 'Size', label: i18next.t('drives.size'),
render: (_description: string, drive: Drive) => { render: (_description: string, drive: Drive) => {
if (isDrivelistDrive(drive) && drive.size !== null) { if (isDrivelistDrive(drive) && drive.size !== null) {
return prettyBytes(drive.size); return prettyBytes(drive.size);
@@ -225,7 +226,7 @@ export class DriveSelector extends React.Component<
{ {
field: 'description', field: 'description',
key: 'link', key: 'link',
label: 'Location', label: i18next.t('drives.location'),
render: (_description: string, drive: Drive) => { render: (_description: string, drive: Drive) => {
return ( return (
<Txt> <Txt>
@@ -399,14 +400,14 @@ export class DriveSelector extends React.Component<
color="#5b82a7" color="#5b82a7"
style={{ fontWeight: 600 }} style={{ fontWeight: 600 }}
> >
{drives.length} found {i18next.t('drives.find', { length: drives.length })}
</Txt> </Txt>
</Flex> </Flex>
} }
titleDetails={<Txt fontSize={11}>{getDrives().length} found</Txt>} titleDetails={<Txt fontSize={11}>{getDrives().length} found</Txt>}
cancel={() => cancel(this.originalList)} cancel={() => cancel(this.originalList)}
done={() => done(selectedList)} done={() => done(selectedList)}
action={`Select (${selectedList.length})`} action={i18next.t('drives.select', { select: selectedList.length })}
primaryButtonProps={{ primaryButtonProps={{
primary: !showWarnings, primary: !showWarnings,
warning: showWarnings, warning: showWarnings,
@@ -512,7 +513,11 @@ export class DriveSelector extends React.Component<
> >
<Flex alignItems="center"> <Flex alignItems="center">
<ChevronDownSvg height="1em" fill="currentColor" /> <ChevronDownSvg height="1em" fill="currentColor" />
<Txt ml={8}>Show {numberOfHiddenSystemDrives} hidden</Txt> <Txt ml={8}>
{i18next.t('drives.showHidden', {
num: numberOfHiddenSystemDrives,
})}
</Txt>
</Flex> </Flex>
</Link> </Link>
)} )}
@@ -520,7 +525,7 @@ export class DriveSelector extends React.Component<
)} )}
{this.props.showWarnings && hasSystemDrives ? ( {this.props.showWarnings && hasSystemDrives ? (
<Alert className="system-drive-alert" style={{ width: '67%' }}> <Alert className="system-drive-alert" style={{ width: '67%' }}>
Selecting your system drive is dangerous and will erase your drive! {i18next.t('drives.systemDriveDanger')}
</Alert> </Alert>
) : null} ) : null}
@@ -540,13 +545,15 @@ export class DriveSelector extends React.Component<
this.setState({ missingDriversModal: {} }); this.setState({ missingDriversModal: {} });
} }
}} }}
action="Yes, continue" action={i18next.t('yesContinue')}
cancelButtonProps={{ cancelButtonProps={{
children: 'Cancel', children: i18next.t('cancel'),
}} }}
children={ children={
missingDriversModal.drive.linkMessage || missingDriversModal.drive.linkMessage ||
`Etcher will open ${missingDriversModal.drive.link} in your browser` i18next.t('drives.openInBrowser', {
link: missingDriversModal.drive.link,
})
} }
/> />
)} )}

View File

@@ -7,6 +7,7 @@ import { middleEllipsis } from '../../utils/middle-ellipsis';
import * as prettyBytes from 'pretty-bytes'; import * as prettyBytes from 'pretty-bytes';
import { DriveWithWarnings } from '../../pages/main/Flash'; import { DriveWithWarnings } from '../../pages/main/Flash';
import * as i18next from 'i18next';
const DriveStatusWarningModal = ({ const DriveStatusWarningModal = ({
done, done,
@@ -17,12 +18,12 @@ const DriveStatusWarningModal = ({
isSystem: boolean; isSystem: boolean;
drivesWithWarnings: DriveWithWarnings[]; drivesWithWarnings: DriveWithWarnings[];
}) => { }) => {
let warningSubtitle = 'You are about to erase an unusually large drive'; let warningSubtitle = i18next.t('drives.largeDriveWarning');
let warningCta = 'Are you sure the selected drive is not a storage drive?'; let warningCta = i18next.t('drives.largeDriveWarningMsg');
if (isSystem) { if (isSystem) {
warningSubtitle = "You are about to erase your computer's drives"; warningSubtitle = i18next.t('drives.systemDriveWarning');
warningCta = 'Are you sure you want to flash your system drive?'; warningCta = i18next.t('drives.systemDriveWarningMsg');
} }
return ( return (
<Modal <Modal
@@ -33,9 +34,9 @@ const DriveStatusWarningModal = ({
cancelButtonProps={{ cancelButtonProps={{
primary: false, primary: false,
warning: true, warning: true,
children: 'Change target', children: i18next.t('drives.changeTarget'),
}} }}
action={"Yes, I'm sure"} action={i18next.t('sure')}
primaryButtonProps={{ primaryButtonProps={{
primary: false, primary: false,
outline: true, outline: true,
@@ -50,7 +51,7 @@ const DriveStatusWarningModal = ({
<Flex flexDirection="column"> <Flex flexDirection="column">
<ExclamationTriangleSvg height="2em" fill="#fca321" /> <ExclamationTriangleSvg height="2em" fill="#fca321" />
<Txt fontSize="24px" color="#fca321"> <Txt fontSize="24px" color="#fca321">
WARNING! {i18next.t('warning')}
</Txt> </Txt>
</Flex> </Flex>
<Txt fontSize="24px">{warningSubtitle}</Txt> <Txt fontSize="24px">{warningSubtitle}</Txt>

View File

@@ -17,6 +17,7 @@
import * as React from 'react'; import * as React from 'react';
import { BaseButton } from '../../styled-components'; import { BaseButton } from '../../styled-components';
import * as i18next from 'i18next';
export interface FlashAnotherProps { export interface FlashAnotherProps {
onClick: () => void; onClick: () => void;
@@ -25,7 +26,7 @@ export interface FlashAnotherProps {
export const FlashAnother = (props: FlashAnotherProps) => { export const FlashAnother = (props: FlashAnotherProps) => {
return ( return (
<BaseButton primary onClick={props.onClick}> <BaseButton primary onClick={props.onClick}>
Flash another {i18next.t('flash.another')}
</BaseButton> </BaseButton>
); );
}; };

View File

@@ -31,6 +31,7 @@ import { resetState } from '../../models/flash-state';
import * as selection from '../../models/selection-state'; import * as selection from '../../models/selection-state';
import { middleEllipsis } from '../../utils/middle-ellipsis'; import { middleEllipsis } from '../../utils/middle-ellipsis';
import { Modal, Table } from '../../styled-components'; import { Modal, Table } from '../../styled-components';
import * as i18next from 'i18next';
const ErrorsTable = styled((props) => <Table<FlashError> {...props} />)` const ErrorsTable = styled((props) => <Table<FlashError> {...props} />)`
&&& [data-display='table-head'], &&& [data-display='table-head'],
@@ -88,15 +89,15 @@ function formattedErrors(errors: FlashError[]) {
const columns: Array<TableColumn<FlashError>> = [ const columns: Array<TableColumn<FlashError>> = [
{ {
field: 'description', field: 'description',
label: 'Target', label: i18next.t('flash.target'),
}, },
{ {
field: 'device', field: 'device',
label: 'Location', label: i18next.t('flash.location'),
}, },
{ {
field: 'message', field: 'message',
label: 'Error', label: i18next.t('flash.error'),
render: (message: string, { code }: FlashError) => { render: (message: string, { code }: FlashError) => {
return message ?? code; return message ?? code;
}, },
@@ -162,9 +163,11 @@ export function FlashResults({
<Txt>{middleEllipsis(image, 24)}</Txt> <Txt>{middleEllipsis(image, 24)}</Txt>
</Flex> </Flex>
<Txt fontSize={24} color="#fff" mb="17px"> <Txt fontSize={24} color="#fff" mb="17px">
Flash {allFailed ? 'Failed' : 'Complete'}! {allFailed
? i18next.t('flash.flashFailed')
: i18next.t('flash.flashCompleted')}
</Txt> </Txt>
{skip ? <Txt color="#7e8085">Validation has been skipped</Txt> : null} {skip ? <Txt color="#7e8085">{i18next.t('flash.skip')}</Txt> : null}
</Flex> </Flex>
<Flex flexDirection="column" color="#7e8085"> <Flex flexDirection="column" color="#7e8085">
{results.devices.successful !== 0 ? ( {results.devices.successful !== 0 ? (
@@ -188,7 +191,7 @@ export function FlashResults({
{progress.failed(errors.length)} {progress.failed(errors.length)}
</Txt> </Txt>
<Link ml="10px" onClick={() => setShowErrorsInfo(true)}> <Link ml="10px" onClick={() => setShowErrorsInfo(true)}>
more info {i18next.t('flash.moreInfo')}
</Link> </Link>
</Flex> </Flex>
) : null} ) : null}
@@ -199,12 +202,9 @@ export function FlashResults({
fontWeight: 500, fontWeight: 500,
textAlign: 'center', textAlign: 'center',
}} }}
tooltip={outdent({ newline: ' ' })` tooltip={i18next.t('flash.speedTip')}
The speed is calculated by dividing the image size by the flashing time.
Disk images with ext partitions flash faster as we are able to skip unused parts.
`}
> >
Effective speed: {effectiveSpeed} MB/s {i18next.t('flash.speed', { speed: effectiveSpeed })}
</Txt> </Txt>
)} )}
</Flex> </Flex>
@@ -214,11 +214,11 @@ export function FlashResults({
titleElement={ titleElement={
<Flex alignItems="baseline" mb={18}> <Flex alignItems="baseline" mb={18}>
<Txt fontSize={24} align="left"> <Txt fontSize={24} align="left">
Failed targets {i18next.t('failedTarget')}
</Txt> </Txt>
</Flex> </Flex>
} }
action="Retry failed targets" action={i18next.t('failedRetry')}
cancel={() => setShowErrorsInfo(false)} cancel={() => setShowErrorsInfo(false)}
done={() => { done={() => {
setShowErrorsInfo(false); setShowErrorsInfo(false);

View File

@@ -20,6 +20,7 @@ import { default as styled } from 'styled-components';
import { fromFlashState } from '../../modules/progress-status'; import { fromFlashState } from '../../modules/progress-status';
import { StepButton } from '../../styled-components'; import { StepButton } from '../../styled-components';
import * as i18next from 'i18next';
const FlashProgressBar = styled(ProgressBar)` const FlashProgressBar = styled(ProgressBar)`
> div { > div {
@@ -28,6 +29,7 @@ const FlashProgressBar = styled(ProgressBar)`
color: white !important; color: white !important;
text-shadow: none !important; text-shadow: none !important;
transition-duration: 0s; transition-duration: 0s;
> div { > div {
transition-duration: 0s; transition-duration: 0s;
} }
@@ -61,7 +63,7 @@ const colors = {
} as const; } as const;
const CancelButton = styled(({ type, onClick, ...props }) => { const CancelButton = styled(({ type, onClick, ...props }) => {
const status = type === 'verifying' ? 'Skip' : 'Cancel'; const status = type === 'verifying' ? i18next.t('skip') : i18next.t('cancel');
return ( return (
<Button plain onClick={() => onClick(status)} {...props}> <Button plain onClick={() => onClick(status)} {...props}>
{status} {status}
@@ -69,6 +71,7 @@ const CancelButton = styled(({ type, onClick, ...props }) => {
); );
})` })`
font-weight: 600; font-weight: 600;
&&& { &&& {
width: auto; width: auto;
height: auto; height: auto;
@@ -126,7 +129,7 @@ export class ProgressButton extends React.PureComponent<ProgressButtonProps> {
marginTop: 30, marginTop: 30,
}} }}
> >
Flash! {i18next.t('flash.flashNow')}
</StepButton> </StepButton>
); );
} }

View File

@@ -24,6 +24,8 @@ import * as settings from '../../models/settings';
import * as analytics from '../../modules/analytics'; import * as analytics from '../../modules/analytics';
import { open as openExternal } from '../../os/open-external/services/open-external'; import { open as openExternal } from '../../os/open-external/services/open-external';
import { Modal } from '../../styled-components'; import { Modal } from '../../styled-components';
import * as i18next from 'i18next';
import { etcherProInfo } from '../../utils/etcher-pro-specific';
interface Setting { interface Setting {
name: string; name: string;
@@ -34,13 +36,17 @@ async function getSettingsList(): Promise<Setting[]> {
const list: Setting[] = [ const list: Setting[] = [
{ {
name: 'errorReporting', name: 'errorReporting',
label: 'Anonymously report errors and usage statistics to balena.io', label: i18next.t('settings.errorReporting'),
},
{
name: 'autoBlockmapping',
label: i18next.t('settings.trimExtPartitions'),
}, },
]; ];
if (['appimage', 'nsis', 'dmg'].includes(packageType)) { if (['appimage', 'nsis', 'dmg'].includes(packageType)) {
list.push({ list.push({
name: 'updatesEnabled', name: 'updatesEnabled',
label: 'Auto-updates enabled', label: i18next.t('settings.autoUpdate'),
}); });
} }
return list; return list;
@@ -50,7 +56,7 @@ interface SettingsModalProps {
toggleModal: (value: boolean) => void; toggleModal: (value: boolean) => void;
} }
const UUID = process.env.BALENA_DEVICE_UUID; const EPInfo = etcherProInfo();
const InfoBox = (props: any) => ( const InfoBox = (props: any) => (
<Box fontSize={14}> <Box fontSize={14}>
@@ -58,6 +64,7 @@ const InfoBox = (props: any) => (
<TextWithCopy code text={props.value} copy={props.value} /> <TextWithCopy code text={props.value} copy={props.value} />
</Box> </Box>
); );
export function SettingsModal({ toggleModal }: SettingsModalProps) { export function SettingsModal({ toggleModal }: SettingsModalProps) {
const [settingsList, setCurrentSettingsList] = React.useState<Setting[]>([]); const [settingsList, setCurrentSettingsList] = React.useState<Setting[]>([]);
React.useEffect(() => { React.useEffect(() => {
@@ -92,7 +99,7 @@ export function SettingsModal({ toggleModal }: SettingsModalProps) {
<Modal <Modal
titleElement={ titleElement={
<Txt fontSize={24} mb={24}> <Txt fontSize={24} mb={24}>
Settings {i18next.t('settings.settings')}
</Txt> </Txt>
} }
done={() => toggleModal(false)} done={() => toggleModal(false)}
@@ -111,10 +118,14 @@ export function SettingsModal({ toggleModal }: SettingsModalProps) {
</Flex> </Flex>
); );
})} })}
{UUID !== undefined && ( {EPInfo !== undefined && (
<Flex flexDirection="column"> <Flex flexDirection="column">
<Txt fontSize={24}>System Information</Txt> <Txt fontSize={24}>{i18next.t('settings.systemInformation')}</Txt>
<InfoBox label="UUID" value={UUID.substr(0, 7)} /> {EPInfo.get_serial() === undefined ? (
<InfoBox label="UUID" value={EPInfo.uuid} />
) : (
<InfoBox label="Serial" value={EPInfo.get_serial()} />
)}
</Flex> </Flex>
)} )}
<Flex <Flex

View File

@@ -66,6 +66,7 @@ import { DriveSelector } from '../drive-selector/drive-selector';
import { DrivelistDrive } from '../../../../shared/drive-constraints'; import { DrivelistDrive } from '../../../../shared/drive-constraints';
import axios, { AxiosRequestConfig } from 'axios'; import axios, { AxiosRequestConfig } from 'axios';
import { isJson } from '../../../../shared/utils'; import { isJson } from '../../../../shared/utils';
import * as i18next from 'i18next';
const recentUrlImagesKey = 'recentUrlImages'; const recentUrlImagesKey = 'recentUrlImages';
@@ -160,7 +161,7 @@ const URLSelector = ({
primaryButtonProps={{ primaryButtonProps={{
disabled: loading || !imageURL, disabled: loading || !imageURL,
}} }}
action={loading ? <Spinner /> : 'OK'} action={loading ? <Spinner /> : i18next.t('ok')}
done={async () => { done={async () => {
setLoading(true); setLoading(true);
const urlStrings = recentImages.map((url: URL) => url.href); const urlStrings = recentImages.map((url: URL) => url.href);
@@ -176,11 +177,11 @@ const URLSelector = ({
<Flex flexDirection="column"> <Flex flexDirection="column">
<Flex mb={15} style={{ width: '100%' }} flexDirection="column"> <Flex mb={15} style={{ width: '100%' }} flexDirection="column">
<Txt mb="10px" fontSize="24px"> <Txt mb="10px" fontSize="24px">
Use Image URL {i18next.t('source.useSourceURL')}
</Txt> </Txt>
<Input <Input
value={imageURL} value={imageURL}
placeholder="Enter a valid URL" placeholder={i18next.t('source.enterValidURL')}
type="text" type="text"
onChange={(evt: React.ChangeEvent<HTMLInputElement>) => onChange={(evt: React.ChangeEvent<HTMLInputElement>) =>
setImageURL(evt.target.value) setImageURL(evt.target.value)
@@ -205,7 +206,7 @@ const URLSelector = ({
{!showBasicAuth && ( {!showBasicAuth && (
<ChevronRightSvg height="1em" fill="currentColor" /> <ChevronRightSvg height="1em" fill="currentColor" />
)} )}
<Txt ml={8}>Authentication</Txt> <Txt ml={8}>{i18next.t('source.auth')}</Txt>
</Flex> </Flex>
</Link> </Link>
{showBasicAuth && ( {showBasicAuth && (
@@ -213,7 +214,7 @@ const URLSelector = ({
<Input <Input
mb={15} mb={15}
value={username} value={username}
placeholder="Enter username" placeholder={i18next.t('source.username')}
type="text" type="text"
onChange={(evt: React.ChangeEvent<HTMLInputElement>) => onChange={(evt: React.ChangeEvent<HTMLInputElement>) =>
setUsername(evt.target.value) setUsername(evt.target.value)
@@ -221,7 +222,7 @@ const URLSelector = ({
/> />
<Input <Input
value={password} value={password}
placeholder="Enter password" placeholder={i18next.t('source.password')}
type="password" type="password"
onChange={(evt: React.ChangeEvent<HTMLInputElement>) => onChange={(evt: React.ChangeEvent<HTMLInputElement>) =>
setPassword(evt.target.value) setPassword(evt.target.value)
@@ -295,7 +296,7 @@ const FlowSelector = styled(
font-weight: 600; font-weight: 600;
svg { svg {
color: ${colors.primary.foreground}!important; color: ${colors.primary.foreground} !important;
} }
} }
`; `;
@@ -453,7 +454,7 @@ export class SourceSelector extends React.Component<
!isURL(this.normalizeImagePath(selected)) !isURL(this.normalizeImagePath(selected))
) { ) {
this.handleError( this.handleError(
'Unsupported protocol', i18next.t('source.unsupportedProtocol'),
selected, selected,
messages.error.unsupportedProtocol(), messages.error.unsupportedProtocol(),
); );
@@ -465,7 +466,7 @@ export class SourceSelector extends React.Component<
this.setState({ this.setState({
warning: { warning: {
message: messages.warning.looksLikeWindowsImage(), message: messages.warning.looksLikeWindowsImage(),
title: 'Possible Windows image detected', title: i18next.t('source.windowsImage'),
}, },
}); });
} }
@@ -491,13 +492,13 @@ export class SourceSelector extends React.Component<
this.setState({ this.setState({
warning: { warning: {
message: messages.warning.missingPartitionTable(), message: messages.warning.missingPartitionTable(),
title: 'Missing partition table', title: i18next.t('source.partitionTable'),
}, },
}); });
} }
} catch (error: any) { } catch (error: any) {
this.handleError( this.handleError(
'Error opening source', i18next.t('source.errorOpen'),
sourcePath, sourcePath,
messages.error.openSource(sourcePath, error.message), messages.error.openSource(sourcePath, error.message),
error, error,
@@ -515,7 +516,7 @@ export class SourceSelector extends React.Component<
this.setState({ this.setState({
warning: { warning: {
message: messages.warning.driveMissingPartitionTable(), message: messages.warning.driveMissingPartitionTable(),
title: 'Missing partition table', title: i18next.t('source.partitionTable'),
}, },
}); });
} }
@@ -719,7 +720,7 @@ export class SourceSelector extends React.Component<
mb={14} mb={14}
onClick={() => this.reselectSource()} onClick={() => this.reselectSource()}
> >
Remove {i18next.t('cancel')}
</ChangeButton> </ChangeButton>
)} )}
{!_.isNil(imageSize) && !imageLoading && ( {!_.isNil(imageSize) && !imageLoading && (
@@ -734,7 +735,7 @@ export class SourceSelector extends React.Component<
key="Flash from file" key="Flash from file"
flow={{ flow={{
onClick: () => this.openImageSelector(), onClick: () => this.openImageSelector(),
label: 'Flash from file', label: i18next.t('source.fromFile'),
icon: <FileSvg height="1em" fill="currentColor" />, icon: <FileSvg height="1em" fill="currentColor" />,
}} }}
onMouseEnter={() => this.setDefaultFlowActive(false)} onMouseEnter={() => this.setDefaultFlowActive(false)}
@@ -744,7 +745,7 @@ export class SourceSelector extends React.Component<
key="Flash from URL" key="Flash from URL"
flow={{ flow={{
onClick: () => this.openURLSelector(), onClick: () => this.openURLSelector(),
label: 'Flash from URL', label: i18next.t('source.fromURL'),
icon: <LinkSvg height="1em" fill="currentColor" />, icon: <LinkSvg height="1em" fill="currentColor" />,
}} }}
onMouseEnter={() => this.setDefaultFlowActive(false)} onMouseEnter={() => this.setDefaultFlowActive(false)}
@@ -754,7 +755,7 @@ export class SourceSelector extends React.Component<
key="Clone drive" key="Clone drive"
flow={{ flow={{
onClick: () => this.openDriveSelector(), onClick: () => this.openDriveSelector(),
label: 'Clone drive', label: i18next.t('source.clone'),
icon: <CopySvg height="1em" fill="currentColor" />, icon: <CopySvg height="1em" fill="currentColor" />,
}} }}
onMouseEnter={() => this.setDefaultFlowActive(false)} onMouseEnter={() => this.setDefaultFlowActive(false)}
@@ -775,7 +776,7 @@ export class SourceSelector extends React.Component<
<span>{this.state.warning.title}</span> <span>{this.state.warning.title}</span>
</span> </span>
} }
action="Continue" action={i18next.t('continue')}
cancel={() => { cancel={() => {
this.setState({ warning: null }); this.setState({ warning: null });
this.reselectSource(); this.reselectSource();
@@ -793,17 +794,17 @@ export class SourceSelector extends React.Component<
{showImageDetails && ( {showImageDetails && (
<SmallModal <SmallModal
title="Image" title={i18next.t('source.image')}
done={() => { done={() => {
this.setState({ showImageDetails: false }); this.setState({ showImageDetails: false });
}} }}
> >
<Txt.p> <Txt.p>
<Txt.span bold>Name: </Txt.span> <Txt.span bold>{i18next.t('source.name')}</Txt.span>
<Txt.span>{imageName || imageBasename}</Txt.span> <Txt.span>{imageName || imageBasename}</Txt.span>
</Txt.p> </Txt.p>
<Txt.p> <Txt.p>
<Txt.span bold>Path: </Txt.span> <Txt.span bold>{i18next.t('source.path')}</Txt.span>
<Txt.span>{imagePath}</Txt.span> <Txt.span>{imagePath}</Txt.span>
</Txt.p> </Txt.p>
</SmallModal> </SmallModal>
@@ -842,8 +843,8 @@ export class SourceSelector extends React.Component<
<DriveSelector <DriveSelector
write={false} write={false}
multipleSelection={false} multipleSelection={false}
titleLabel="Select source" titleLabel={i18next.t('source.selectSource')}
emptyListLabel="Plug a source drive" emptyListLabel={i18next.t('source.plugSource')}
emptyListIcon={<SrcSvg width="40px" />} emptyListIcon={<SrcSvg width="40px" />}
cancel={(originalList) => { cancel={(originalList) => {
if (originalList.length) { if (originalList.length) {

View File

@@ -32,6 +32,7 @@ import {
StepNameButton, StepNameButton,
} from '../../styled-components'; } from '../../styled-components';
import { middleEllipsis } from '../../utils/middle-ellipsis'; import { middleEllipsis } from '../../utils/middle-ellipsis';
import * as i18next from 'i18next';
interface TargetSelectorProps { interface TargetSelectorProps {
targets: any[]; targets: any[];
@@ -95,7 +96,7 @@ export function TargetSelectorButton(props: TargetSelectorProps) {
</StepNameButton> </StepNameButton>
{!props.flashing && ( {!props.flashing && (
<ChangeButton plain mb={14} onClick={props.reselectDrive}> <ChangeButton plain mb={14} onClick={props.reselectDrive}>
Change {i18next.t('target.change')}
</ChangeButton> </ChangeButton>
)} )}
{target.size != null && ( {target.size != null && (
@@ -132,11 +133,11 @@ export function TargetSelectorButton(props: TargetSelectorProps) {
return ( return (
<> <>
<StepNameButton plain tooltip={props.tooltip}> <StepNameButton plain tooltip={props.tooltip}>
{targets.length} Targets {targets.length} {i18next.t('target.targets')}
</StepNameButton> </StepNameButton>
{!props.flashing && ( {!props.flashing && (
<ChangeButton plain onClick={props.reselectDrive} mb={14}> <ChangeButton plain onClick={props.reselectDrive} mb={14}>
Change {i18next.t('target.change')}
</ChangeButton> </ChangeButton>
)} )}
{targetsTemplate} {targetsTemplate}
@@ -151,7 +152,7 @@ export function TargetSelectorButton(props: TargetSelectorProps) {
disabled={props.disabled} disabled={props.disabled}
onClick={props.openDriveSelector} onClick={props.openDriveSelector}
> >
Select target {i18next.t('target.selectTarget')}
</StepButton> </StepButton>
); );
} }

View File

@@ -37,6 +37,7 @@ import TgtSvg from '../../../assets/tgt.svg';
import DriveSvg from '../../../assets/drive.svg'; import DriveSvg from '../../../assets/drive.svg';
import { warning } from '../../../../shared/messages'; import { warning } from '../../../../shared/messages';
import { DrivelistDrive } from '../../../../shared/drive-constraints'; import { DrivelistDrive } from '../../../../shared/drive-constraints';
import * as i18next from 'i18next';
export const getDriveListLabel = () => { export const getDriveListLabel = () => {
return getSelectedDrives() return getSelectedDrives()
@@ -60,8 +61,8 @@ export const TargetSelectorModal = (
) => ( ) => (
<DriveSelector <DriveSelector
multipleSelection={true} multipleSelection={true}
titleLabel="Select target" titleLabel={i18next.t('target.selectTarget')}
emptyListLabel="Plug a target drive" emptyListLabel={i18next.t('target.plugTarget')}
emptyListIcon={<TgtSvg width="40px" />} emptyListIcon={<TgtSvg width="40px" />}
showWarnings={true} showWarnings={true}
selectedList={getSelectedDrives()} selectedList={getSelectedDrives()}

42
lib/gui/app/i18n.ts Normal file
View File

@@ -0,0 +1,42 @@
import * as i18next from 'i18next';
import { initReactI18next } from 'react-i18next';
import zh_CN_translation from './i18n/zh-CN';
import zh_TW_translation from './i18n/zh-TW';
import en_translation from './i18n/en';
export function langParser() {
if (process.env.LANG !== undefined) {
// Bypass mocha, where lang-detect don't works
return 'en';
}
const lang = Intl.DateTimeFormat().resolvedOptions().locale;
switch (lang.substr(0, 2)) {
case 'zh':
if (lang === 'zh-CN' || lang === 'zh-SG') {
return 'zh-CN';
} // Simplified Chinese
else {
return 'zh-TW';
} // Traditional Chinese
default:
return lang.substr(0, 2);
}
}
i18next.use(initReactI18next).init({
lng: langParser(),
fallbackLng: 'en',
nonExplicitSupportedLngs: true,
interpolation: {
escapeValue: false,
},
resources: {
'zh-CN': zh_CN_translation,
'zh-TW': zh_TW_translation,
en: en_translation,
},
});
export default i18next;

View File

@@ -0,0 +1,23 @@
# i18n
## How it was done
Using the open-source lib [i18next](https://www.i18next.com/).
## How to add your own language
1. Go to `lib/gui/app/i18n` and add a file named `xx.ts` (use the codes mentioned
in [the link](https://www.science.co.il/language/Locale-codes.php), and we support styles as `fr`, `de`, `es-ES`
and `pt-BR`)
.
2. Copy the content from an existing translation and start to translate.
3. Once done, go to `lib/gui/app/i18n.ts` and add a line of `import xx_translation from './i18n/xx'` after the
already-added imports and add `xx: xx_translation` in the `resources` section of `i18next.init()` function.
4. Now go to `lib/shared/catalina-sudo/` and copy the `sudo-askpass.osascript-en.js`, change it to
be `sudo-askpass.osascript-xx.js` and edit
the `'balenaEtcher needs privileged access in order to flash disks.\n\nType your password to allow this.'` line and
those `Ok`s and `Cancel`s to your own language.
5. If, your language has several variations when they are used in several countries/regions, such as `zh-CN` and `zh-TW`
, or `pt-BR` and `pt-PT`, edit
the `langParser()` in the `lib/gui/app/i18n.ts` file to meet your need.
6. Make a commit, and then a pull request on GitHub.

161
lib/gui/app/i18n/en.ts Normal file
View File

@@ -0,0 +1,161 @@
const translation = {
translation: {
continue: 'Continue',
ok: 'OK',
cancel: 'Cancel',
skip: 'Skip',
sure: "Yes, I'm sure",
warning: 'WARNING! ',
attention: 'Attention',
failed: 'Failed',
completed: 'Completed',
yesContinue: 'Yes, continue',
reallyExit: 'Are you sure you want to close Etcher?',
yesExit: 'Yes, quit',
progress: {
starting: 'Starting...',
decompressing: 'Decompressing...',
flashing: 'Flashing...',
finishing: 'Finishing...',
verifying: 'Validating...',
failing: 'Failed',
},
message: {
sizeNotRecommended: 'Not recommended',
tooSmall: 'Too small',
locked: 'Locked',
system: 'System drive',
containsImage: 'Source drive',
largeDrive: 'Large drive',
sourceLarger: 'The selected source is {{byte}} larger than this drive.',
flashSucceed_one: 'Successful target',
flashSucceed_other: 'Successful targets',
flashFail_one: 'Failed target',
flashFail_other: 'Failed targets',
toDrive: 'to {{description}} ({{name}})',
toTarget_one: 'to {{num}} target',
toTarget_other: 'to {{num}} targets',
andFailTarget_one: 'and failed to be flashed to {{num}} target',
andFailTarget_other: 'and failed to be flashed to {{num}} targets',
succeedTo: '{{name}} was successfully flashed {{target}}',
exitWhileFlashing:
'You are currently flashing a drive. Closing Etcher may leave your drive in an unusable state.',
looksLikeWindowsImage:
'It looks like you are trying to burn a Windows image.\n\nUnlike other images, Windows images require special processing to be made bootable. We suggest you use a tool specially designed for this purpose, such as <a href="https://rufus.akeo.ie">Rufus</a> (Windows), <a href="https://github.com/slacka/WoeUSB">WoeUSB</a> (Linux), or Boot Camp Assistant (macOS).',
image: 'image',
drive: 'drive',
missingPartitionTable:
'It looks like this is not a bootable {{type}}.\n\nThe {{type}} does not appear to contain a partition table, and might not be recognized or bootable by your device.',
largeDriveSize:
"This is a large drive! Make sure it doesn't contain files that you want to keep.",
systemDrive:
'Selecting your system drive is dangerous and will erase your drive!',
sourceDrive: 'Contains the image you chose to flash',
noSpace:
'Not enough space on the drive. Please insert larger one and try again.',
genericFlashError:
'Something went wrong. If it is a compressed image, please check that the archive is not corrupted.\n{{error}}',
validation:
'The write has been completed successfully but Etcher detected potential corruption issues when reading the image back from the drive. \n\nPlease consider writing the image to a different drive.',
openError:
'Something went wrong while opening {{source}}.\n\nError: {{error}}',
flashError: 'Something went wrong while writing {{image}} {{targets}}.',
unplug:
"Looks like Etcher lost access to the drive. Did it get unplugged accidentally?\n\nSometimes this error is caused by faulty readers that don't provide stable access to the drive.",
cannotWrite:
'Looks like Etcher is not able to write to this location of the drive. This error is usually caused by a faulty drive, reader, or port. \n\nPlease try again with another drive, reader, or port.',
childWriterDied:
'The writer process ended unexpectedly. Please try again, and contact the Etcher team if the problem persists.',
badProtocol: 'Only http:// and https:// URLs are supported.',
},
target: {
selectTarget: 'Select target',
plugTarget: 'Plug a target drive',
targets: 'Targets',
change: 'Change',
},
source: {
useSourceURL: 'Use Image URL',
auth: 'Authentication',
username: 'Enter username',
password: 'Enter password',
unsupportedProtocol: 'Unsupported protocol',
windowsImage: 'Possible Windows image detected',
partitionTable: 'Missing partition table',
errorOpen: 'Error opening source',
fromFile: 'Flash from file',
fromURL: 'Flash from URL',
clone: 'Clone drive',
image: 'Image',
name: 'Name: ',
path: 'Path: ',
selectSource: 'Select source',
plugSource: 'Plug a source drive',
osImages: 'OS Images',
allFiles: 'All',
enterValidURL: 'Enter a valid URL',
},
drives: {
name: 'Name',
size: 'Size',
location: 'Location',
find: '{{length}} found',
select: 'Select {{select}}',
showHidden: 'Show {{num}} hidden',
systemDriveDanger:
'Selecting your system drive is dangerous and will erase your drive!',
openInBrowser: '`Etcher will open {{link}} in your browser`',
changeTarget: 'Change target',
largeDriveWarning: 'You are about to erase an unusually large drive',
largeDriveWarningMsg:
'Are you sure the selected drive is not a storage drive?',
systemDriveWarning: "You are about to erase your computer's drives",
systemDriveWarningMsg:
'Are you sure you want to flash your system drive?',
},
flash: {
another: 'Flash another',
target: 'Target',
location: 'Location',
error: 'Error',
flash: 'Flash',
flashNow: 'Flash!',
skip: 'Validation has been skipped',
moreInfo: 'more info',
speedTip:
'The speed is calculated by dividing the image size by the flashing time.\nDisk images with ext partitions flash faster as we are able to skip unused parts.',
speed: 'Effective speed: {{speed}} MB/s',
speedShort: '{{speed}} MB/s',
eta: 'ETA: {{eta}}',
failedTarget: 'Failed targets',
failedRetry: 'Retry failed targets',
flashFailed: 'Flash Failed.',
flashCompleted: 'Flash Completed!',
},
settings: {
errorReporting:
'Anonymously report errors and usage statistics to balena.io',
autoUpdate: 'Auto-updates enabled',
settings: 'Settings',
systemInformation: 'System Information',
trimExtPartitions: 'Trim unallocated space on raw images (in ext-type partitions)',
},
menu: {
edit: 'Edit',
view: 'View',
devTool: 'Toggle Developer Tools',
window: 'Window',
help: 'Help',
pro: 'Etcher Pro',
website: 'Etcher Website',
issue: 'Report an issue',
about: 'About Etcher',
hide: 'Hide Etcher',
hideOthers: 'Hide Others',
unhide: 'Unhide All',
quit: 'Quit Etcher',
},
},
};
export default translation;

152
lib/gui/app/i18n/zh-CN.ts Normal file
View File

@@ -0,0 +1,152 @@
const translation = {
translation: {
ok: '好',
cancel: '取消',
continue: '继续',
skip: '跳过',
sure: '我确定',
warning: '请注意!',
attention: '请注意',
failed: '失败',
completed: '完毕',
yesExit: '是的,可以退出',
reallyExit: '真的要现在退出 Etcher 吗?',
yesContinue: '是的,继续',
progress: {
starting: '正在启动……',
decompressing: '正在解压……',
flashing: '正在烧录……',
finishing: '正在结束……',
verifying: '正在验证……',
failing: '失败……',
},
message: {
sizeNotRecommended: '大小不推荐',
tooSmall: '空间太小',
locked: '被锁定',
system: '系统盘',
containsImage: '存放源镜像',
largeDrive: '很大的磁盘',
sourceLarger: '所选的镜像比目标盘大了 {{byte}} 比特。',
flashSucceed_one: '烧录成功',
flashSucceed_other: '烧录成功',
flashFail_one: '烧录失败',
flashFail_other: '烧录失败',
toDrive: '到 {{description}} ({{name}})',
toTarget_one: '到 {{num}} 个目标',
toTarget_other: '到 {{num}} 个目标',
andFailTarget_one: '并烧录失败了 {{num}} 个目标',
andFailTarget_other: '并烧录失败了 {{num}} 个目标',
succeedTo: '{{name}} 被成功烧录 {{target}}',
exitWhileFlashing:
'您当前正在刷机。 关闭 Etcher 可能会导致您的磁盘无法使用。',
looksLikeWindowsImage:
'看起来您正在尝试刻录 Windows 镜像。\n\n与其他镜像不同Windows 镜像需要特殊处理才能使其可启动。 我们建议您使用专门为此目的设计的工具,例如 <a href="https://rufus.akeo.ie">Rufus</a> (Windows)、<a href="https://github. com/slacka/WoeUSB">WoeUSB</a> (Linux) 或 Boot Camp 助理 (macOS)。',
image: '镜像',
drive: '磁盘',
missingPartitionTable:
'看起来这不是一个可启动的{{type}}。\n\n这个{{type}}似乎不包含分区表,因此您的设备可能无法识别或无法正确启动。',
largeDriveSize: '这是个很大的磁盘!请检查并确认它不包含对您很重要的信息',
systemDrive: '选择系统盘很危险,因为这将会删除你的系统',
sourceDrive: '源镜像位于这个分区中',
noSpace: '磁盘空间不足。 请插入另一个较大的磁盘并重试。',
genericFlashError:
'出了点问题。如果源镜像曾被压缩过,请检查它是否已损坏。\n{{error}}',
validation:
'写入已成功完成,但 Etcher 在从磁盘读取镜像时检测到潜在的损坏问题。 \n\n请考虑将镜像写入其他磁盘。',
openError: '打开 {{source}} 时出错。\n\n错误信息 {{error}}',
flashError: '烧录 {{image}} {{targets}} 失败。',
unplug:
'看起来 Etcher 失去了对磁盘的连接。 它是不是被意外拔掉了?\n\n有时这个错误是因为读卡器出了故障。',
cannotWrite:
'看起来 Etcher 无法写入磁盘的这个位置。 此错误通常是由故障的磁盘、读取器或端口引起的。 \n\n请使用其他磁盘、读卡器或端口重试。',
childWriterDied:
'写入进程意外崩溃。请再试一次,如果问题仍然存在,请联系 Etcher 团队。',
badProtocol: '仅支持 http:// 和 https:// 开头的网址。',
},
target: {
selectTarget: '选择目标磁盘',
plugTarget: '请插入目标磁盘',
targets: '个目标',
change: '更改',
},
menu: {
edit: '编辑',
view: '视图',
devTool: '打开开发者工具',
window: '窗口',
help: '帮助',
pro: 'Etcher 专业版',
website: 'Etcher 的官网',
issue: '提交一个 issue',
about: '关于 Etcher',
hide: '隐藏 Etcher',
hideOthers: '隐藏其它窗口',
unhide: '取消隐藏',
quit: '退出 Etcher',
},
source: {
useSourceURL: '使用镜像网络地址',
auth: '验证',
username: '输入用户名',
password: '输入密码',
unsupportedProtocol: '不支持的协议',
windowsImage: '这可能是 Windows 系统镜像',
partitionTable: '找不到分区表',
errorOpen: '打开源镜像时出错',
fromFile: '从文件烧录',
fromURL: '从在线地址烧录',
clone: '克隆磁盘',
image: '镜像信息',
name: '名称:',
path: '路径:',
selectSource: '选择源',
plugSource: '请插入源磁盘',
osImages: '系统镜像格式',
allFiles: '任何文件格式',
enterValidURL: '请输入一个正确的地址',
},
drives: {
name: '名称',
size: '大小',
location: '位置',
find: '找到 {{length}} 个',
select: '选定 {{select}}',
showHidden: '显示 {{num}} 个隐藏的磁盘',
systemDriveDanger: '选择系统盘很危险,因为这将会删除你的系统!',
openInBrowser: 'Etcher 会在浏览器中打开 {{link}}',
changeTarget: '改变目标',
largeDriveWarning: '您即将擦除一个非常大的磁盘',
largeDriveWarningMsg: '您确定所选磁盘不是存储磁盘吗?',
systemDriveWarning: '您将要擦除系统盘',
systemDriveWarningMsg: '您确定要烧录到系统盘吗?',
},
flash: {
another: '烧录另一目标',
target: '目标',
location: '位置',
error: '错误',
flash: '烧录',
flashNow: '现在烧录!',
skip: '跳过了验证',
moreInfo: '更多信息',
speedTip:
'通过将镜像大小除以烧录时间来计算速度。\n由于我们能够跳过未使用的部分因此具有EXT分区的磁盘镜像烧录速度更快。',
speed: '速度:{{speed}} MB/秒',
speedShort: '{{speed}} MB/秒',
eta: '预计还需要:{{eta}}',
failedTarget: '失败的烧录目标',
failedRetry: '重试烧录失败目标',
flashFailed: '烧录失败。',
flashCompleted: '烧录成功!',
},
settings: {
errorReporting: '匿名地向 balena.io 报告运行错误和使用统计',
autoUpdate: '自动更新',
settings: '软件设置',
systemInformation: '系统信息',
},
},
};
export default translation;

152
lib/gui/app/i18n/zh-TW.ts Normal file
View File

@@ -0,0 +1,152 @@
const translation = {
translation: {
ok: '好',
cancel: '取消',
continue: '繼續',
skip: '跳過',
sure: '我確定',
warning: '請注意!',
attention: '請注意',
failed: '失敗',
completed: '完畢',
yesExit: '是的,可以退出',
reallyExit: '真的要現在退出 Etcher 嗎?',
yesContinue: '是的,繼續',
progress: {
starting: '正在啓動……',
decompressing: '正在解壓……',
flashing: '正在燒錄……',
finishing: '正在結束……',
verifying: '正在驗證……',
failing: '失敗……',
},
message: {
sizeNotRecommended: '大小不推薦',
tooSmall: '空間太小',
locked: '被鎖定',
system: '系統盤',
containsImage: '存放源鏡像',
largeDrive: '很大的磁盤',
sourceLarger: '所選的鏡像比目標盤大了 {{byte}} 比特。',
flashSucceed_one: '燒錄成功',
flashSucceed_other: '燒錄成功',
flashFail_one: '燒錄失敗',
flashFail_other: '燒錄失敗',
toDrive: '到 {{description}} ({{name}})',
toTarget_one: '到 {{num}} 個目標',
toTarget_other: '到 {{num}} 個目標',
andFailTarget_one: '並燒錄失敗了 {{num}} 個目標',
andFailTarget_other: '並燒錄失敗了 {{num}} 個目標',
succeedTo: '{{name}} 被成功燒錄 {{target}}',
exitWhileFlashing:
'您當前正在刷機。 關閉 Etcher 可能會導致您的磁盤無法使用。',
looksLikeWindowsImage:
'看起來您正在嘗試刻錄 Windows 鏡像。\n\n與其他鏡像不同Windows 鏡像需要特殊處理才能使其可啓動。 我們建議您使用專門爲此目的設計的工具,例如 <a href="https://rufus.akeo.ie">Rufus</a> (Windows)、<a href="https://github. com/slacka/WoeUSB">WoeUSB</a> (Linux) 或 Boot Camp 助理 (macOS)。',
image: '鏡像',
drive: '磁盤',
missingPartitionTable:
'看起來這不是一個可啓動的{{type}}。\n\n這個{{type}}似乎不包含分區表,因此您的設備可能無法識別或無法正確啓動。',
largeDriveSize: '這是個很大的磁盤!請檢查並確認它不包含對您很重要的信息',
systemDrive: '選擇系統盤很危險,因爲這將會刪除你的系統',
sourceDrive: '源鏡像位於這個分區中',
noSpace: '磁盤空間不足。 請插入另一個較大的磁盤並重試。',
genericFlashError:
'出了點問題。如果源鏡像曾被壓縮過,請檢查它是否已損壞。\n{{error}}',
validation:
'寫入已成功完成,但 Etcher 在從磁盤讀取鏡像時檢測到潛在的損壞問題。 \n\n請考慮將鏡像寫入其他磁盤。',
openError: '打開 {{source}} 時出錯。\n\n錯誤信息 {{error}}',
flashError: '燒錄 {{image}} {{targets}} 失敗。',
unplug:
'看起來 Etcher 失去了對磁盤的連接。 它是不是被意外拔掉了?\n\n有時這個錯誤是因爲讀卡器出了故障。',
cannotWrite:
'看起來 Etcher 無法寫入磁盤的這個位置。 此錯誤通常是由故障的磁盤、讀取器或端口引起的。 \n\n請使用其他磁盤、讀卡器或端口重試。',
childWriterDied:
'寫入進程意外崩潰。請再試一次,如果問題仍然存在,請聯繫 Etcher 團隊。',
badProtocol: '僅支持 http:// 和 https:// 開頭的網址。',
},
target: {
selectTarget: '選擇目標磁盤',
plugTarget: '請插入目標磁盤',
targets: '個目標',
change: '更改',
},
menu: {
edit: '編輯',
view: '視圖',
devTool: '打開開發者工具',
window: '窗口',
help: '幫助',
pro: 'Etcher 專業版',
website: 'Etcher 的官網',
issue: '提交一個 issue',
about: '關於 Etcher',
hide: '隱藏 Etcher',
hideOthers: '隱藏其它窗口',
unhide: '取消隱藏',
quit: '退出 Etcher',
},
source: {
useSourceURL: '使用鏡像網絡地址',
auth: '驗證',
username: '輸入用戶名',
password: '輸入密碼',
unsupportedProtocol: '不支持的協議',
windowsImage: '這可能是 Windows 系統鏡像',
partitionTable: '找不到分區表',
errorOpen: '打開源鏡像時出錯',
fromFile: '從文件燒錄',
fromURL: '從在線地址燒錄',
clone: '克隆磁盤',
image: '鏡像信息',
name: '名稱:',
path: '路徑:',
selectSource: '選擇源',
plugSource: '請插入源磁盤',
osImages: '系統鏡像格式',
allFiles: '任何文件格式',
enterValidURL: '請輸入一個正確的地址',
},
drives: {
name: '名稱',
size: '大小',
location: '位置',
find: '找到 {{length}} 個',
select: '選定 {{select}}',
showHidden: '顯示 {{num}} 個隱藏的磁盤',
systemDriveDanger: '選擇系統盤很危險,因爲這將會刪除你的系統!',
openInBrowser: 'Etcher 會在瀏覽器中打開 {{link}}',
changeTarget: '改變目標',
largeDriveWarning: '您即將擦除一個非常大的磁盤',
largeDriveWarningMsg: '您確定所選磁盤不是存儲磁盤嗎?',
systemDriveWarning: '您將要擦除系統盤',
systemDriveWarningMsg: '您確定要燒錄到系統盤嗎?',
},
flash: {
another: '燒錄另一目標',
target: '目標',
location: '位置',
error: '錯誤',
flash: '燒錄',
flashNow: '現在燒錄!',
skip: '跳過了驗證',
moreInfo: '更多信息',
speedTip:
'通過將鏡像大小除以燒錄時間來計算速度。\n由於我們能夠跳過未使用的部分因此具有EXT分區的磁盤鏡像燒錄速度更快。',
speed: '速度:{{speed}} MB/秒',
speedShort: '{{speed}} MB/秒',
eta: '預計還需要:{{eta}}',
failedTarget: '失敗的燒錄目標',
failedRetry: '重試燒錄失敗目標',
flashFailed: '燒錄失敗。',
flashCompleted: '燒錄成功!',
},
settings: {
errorReporting: '匿名地向 balena.io 報告運行錯誤和使用統計',
autoUpdate: '自動更新',
settings: '軟件設置',
systemInformation: '系統信息',
},
},
};
export default translation;

View File

@@ -18,7 +18,6 @@ import * as electron from 'electron';
import * as sdk from 'etcher-sdk'; import * as sdk from 'etcher-sdk';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { DrivelistDrive } from '../../../shared/drive-constraints'; import { DrivelistDrive } from '../../../shared/drive-constraints';
import { bytesToMegabytes } from '../../../shared/units'; import { bytesToMegabytes } from '../../../shared/units';
import { Actions, store } from './store'; import { Actions, store } from './store';
@@ -48,7 +47,7 @@ export function isFlashing(): boolean {
*/ */
export function setFlashingFlag() { export function setFlashingFlag() {
// see https://github.com/balenablocks/balena-electron-env/blob/4fce9c461f294d4a768db8f247eea6f75d7b08b0/README.md#remote-methods // see https://github.com/balenablocks/balena-electron-env/blob/4fce9c461f294d4a768db8f247eea6f75d7b08b0/README.md#remote-methods
electron.ipcRenderer.send('disable-screensaver'); electron.ipcRenderer.invoke('disable-screensaver');
store.dispatch({ store.dispatch({
type: Actions.SET_FLASHING_FLAG, type: Actions.SET_FLASHING_FLAG,
data: {}, data: {},
@@ -71,7 +70,7 @@ export function unsetFlashingFlag(results: {
data: results, data: results,
}); });
// see https://github.com/balenablocks/balena-electron-env/blob/4fce9c461f294d4a768db8f247eea6f75d7b08b0/README.md#remote-methods // see https://github.com/balenablocks/balena-electron-env/blob/4fce9c461f294d4a768db8f247eea6f75d7b08b0/README.md#remote-methods
electron.ipcRenderer.send('enable-screensaver'); electron.ipcRenderer.invoke('enable-screensaver');
} }
export function setDevicePaths(devicePaths: string[]) { export function setDevicePaths(devicePaths: string[]) {

View File

@@ -15,6 +15,7 @@
*/ */
import * as prettyBytes from 'pretty-bytes'; import * as prettyBytes from 'pretty-bytes';
import * as i18next from 'i18next';
export interface FlashState { export interface FlashState {
active: number; active: number;
@@ -34,36 +35,45 @@ export function fromFlashState({
position?: string; position?: string;
} { } {
if (type === undefined) { if (type === undefined) {
return { status: 'Starting...' }; return { status: i18next.t('progress.starting') };
} else if (type === 'decompressing') { } else if (type === 'decompressing') {
if (percentage == null) { if (percentage == null) {
return { status: 'Decompressing...' }; return { status: i18next.t('progress.decompressing') };
} else { } else {
return { position: `${percentage}%`, status: 'Decompressing...' }; return {
position: `${percentage}%`,
status: i18next.t('progress.decompressing'),
};
} }
} else if (type === 'flashing') { } else if (type === 'flashing') {
if (percentage != null) { if (percentage != null) {
if (percentage < 100) { if (percentage < 100) {
return { position: `${percentage}%`, status: 'Flashing...' }; return {
position: `${percentage}%`,
status: i18next.t('progress.flashing'),
};
} else { } else {
return { status: 'Finishing...' }; return { status: i18next.t('progress.finishing') };
} }
} else { } else {
return { return {
status: 'Flashing...', status: i18next.t('progress.flashing'),
position: `${position ? prettyBytes(position) : ''}`, position: `${position ? prettyBytes(position) : ''}`,
}; };
} }
} else if (type === 'verifying') { } else if (type === 'verifying') {
if (percentage == null) { if (percentage == null) {
return { status: 'Validating...' }; return { status: i18next.t('progress.verifying') };
} else if (percentage < 100) { } else if (percentage < 100) {
return { position: `${percentage}%`, status: 'Validating...' }; return {
position: `${percentage}%`,
status: i18next.t('progress.verifying'),
};
} else { } else {
return { status: 'Finishing...' }; return { status: i18next.t('progress.finishing') };
} }
} }
return { status: 'Failed' }; return { status: i18next.t('progress.failing') };
} }
export function titleFromFlashState( export function titleFromFlashState(

View File

@@ -20,6 +20,7 @@ import * as _ from 'lodash';
import * as errors from '../../../shared/errors'; import * as errors from '../../../shared/errors';
import * as settings from '../../../gui/app/models/settings'; import * as settings from '../../../gui/app/models/settings';
import { SUPPORTED_EXTENSIONS } from '../../../shared/supported-formats'; import { SUPPORTED_EXTENSIONS } from '../../../shared/supported-formats';
import * as i18next from 'i18next';
async function mountSourceDrive() { async function mountSourceDrive() {
// sourceDrivePath is the name of the link in /dev/disk/by-path // sourceDrivePath is the name of the link in /dev/disk/by-path
@@ -53,11 +54,11 @@ export async function selectImage(): Promise<string | undefined> {
properties: ['openFile', 'treatPackageAsDirectory'], properties: ['openFile', 'treatPackageAsDirectory'],
filters: [ filters: [
{ {
name: 'OS Images', name: i18next.t('source.osImages'),
extensions: SUPPORTED_EXTENSIONS, extensions: SUPPORTED_EXTENSIONS,
}, },
{ {
name: 'All', name: i18next.t('source.allFiles'),
extensions: ['*'], extensions: ['*'],
}, },
], ],
@@ -79,8 +80,8 @@ export async function showWarning(options: {
description: string; description: string;
}): Promise<boolean> { }): Promise<boolean> {
_.defaults(options, { _.defaults(options, {
confirmationLabel: 'OK', confirmationLabel: i18next.t('ok'),
rejectionLabel: 'Cancel', rejectionLabel: i18next.t('cancel'),
}); });
const BUTTONS = [options.confirmationLabel, options.rejectionLabel]; const BUTTONS = [options.confirmationLabel, options.rejectionLabel];
@@ -98,7 +99,7 @@ export async function showWarning(options: {
buttons: BUTTONS, buttons: BUTTONS,
defaultId: BUTTON_REJECTION_INDEX, defaultId: BUTTON_REJECTION_INDEX,
cancelId: BUTTON_REJECTION_INDEX, cancelId: BUTTON_REJECTION_INDEX,
title: 'Attention', title: i18next.t('attention'),
message: options.title, message: options.title,
detail: options.description, detail: options.description,
}, },

View File

@@ -37,6 +37,7 @@ import {
import FlashSvg from '../../../assets/flash.svg'; import FlashSvg from '../../../assets/flash.svg';
import DriveStatusWarningModal from '../../components/drive-status-warning-modal/drive-status-warning-modal'; import DriveStatusWarningModal from '../../components/drive-status-warning-modal/drive-status-warning-modal';
import * as i18next from 'i18next';
const COMPLETED_PERCENTAGE = 100; const COMPLETED_PERCENTAGE = 100;
const SPEED_PRECISION = 2; const SPEED_PRECISION = 2;
@@ -293,9 +294,17 @@ export class FlashStep extends React.PureComponent<
color="#7e8085" color="#7e8085"
width="100%" width="100%"
> >
<Txt>{this.props.speed.toFixed(SPEED_PRECISION)} MB/s</Txt> <Txt>
{i18next.t('flash.speedShort', {
speed: this.props.speed.toFixed(SPEED_PRECISION),
})}
</Txt>
{!_.isNil(this.props.eta) && ( {!_.isNil(this.props.eta) && (
<Txt>ETA: {formatSeconds(this.props.eta)}</Txt> <Txt>
{i18next.t('flash.eta', {
eta: formatSeconds(this.props.eta),
})}
</Txt>
)} )}
</Flex> </Flex>
)} )}

View File

@@ -1,5 +1,10 @@
// @ts-nocheck // @ts-nocheck
import { main } from './app'; import { main } from './app';
import './i18n';
import { langParser } from './i18n';
import { ipcRenderer } from 'electron';
ipcRenderer.send('change-lng', langParser());
if (module.hot) { if (module.hot) {
module.hot.accept('./app', () => { module.hot.accept('./app', () => {

View File

@@ -142,7 +142,7 @@ export const Modal = styled(({ style, children, ...props }) => {
{...props} {...props}
> >
<ScrollableFlex flexDirection="column" width="100%" height="90%"> <ScrollableFlex flexDirection="column" width="100%" height="90%">
{...children} {children.length ? children.map((c: any) => <>{c}</>) : children}
</ScrollableFlex> </ScrollableFlex>
</ModalBase> </ModalBase>
); );

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2022 balena.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Dictionary } from 'lodash';
type BalenaTag = {
id: number,
name: string,
value: string
}
export class EtcherPro {
private supervisorAddr: string;
private supervisorKey: string;
private tags: Dictionary<string> | undefined;
public uuid: string;
constructor(supervisorAddr: string, supervisorKey: string) {
this.supervisorAddr = supervisorAddr;
this.supervisorKey = supervisorKey;
this.uuid = (process.env.BALENA_DEVICE_UUID ?? 'NO-UUID').substring(0, 7);
this.tags = undefined;
this.get_tags().then((tags) => (this.tags = tags));
}
async get_tags(): Promise<Dictionary<string>> {
const result = await fetch(
this.supervisorAddr + '/v2/device/tags?apikey=' + this.supervisorKey,
);
const parsed = await result.json();
if (parsed['status'] === 'success') {
return Object.assign(
{},
...parsed['tags'].map((tag: BalenaTag) => {
return { [tag.name]: tag.value };
}),
);
} else {
return {};
}
}
public get_serial(): string | undefined {
if (this.tags) {
return this.tags['Serial'];
} else {
return undefined;
}
}
}
export function etcherProInfo(): EtcherPro | undefined {
const BALENA_SUPERVISOR_ADDRESS = process.env.BALENA_SUPERVISOR_ADDRESS;
const BALENA_SUPERVISOR_API_KEY = process.env.BALENA_SUPERVISOR_API_KEY;
if (BALENA_SUPERVISOR_ADDRESS && BALENA_SUPERVISOR_API_KEY) {
return new EtcherPro(BALENA_SUPERVISOR_ADDRESS, BALENA_SUPERVISOR_API_KEY);
}
return undefined;
}

View File

@@ -21,18 +21,22 @@ import { platform } from 'os';
import * as path from 'path'; import * as path from 'path';
import * as semver from 'semver'; import * as semver from 'semver';
import './app/i18n';
import { packageType, version } from '../../package.json'; import { packageType, version } from '../../package.json';
import * as EXIT_CODES from '../shared/exit-codes'; import * as EXIT_CODES from '../shared/exit-codes';
import { delay, getConfig } from '../shared/utils'; import { delay, getConfig } from '../shared/utils';
import * as settings from './app/models/settings'; import * as settings from './app/models/settings';
import { logException } from './app/modules/analytics'; import { logException } from './app/modules/analytics';
import { buildWindowMenu } from './menu'; import { buildWindowMenu } from './menu';
import * as i18n from 'i18next';
const customProtocol = 'etcher'; const customProtocol = 'etcher';
const scheme = `${customProtocol}://`; const scheme = `${customProtocol}://`;
const updatablePackageTypes = ['appimage', 'nsis', 'dmg']; const updatablePackageTypes = ['appimage', 'nsis', 'dmg'];
const packageUpdatable = updatablePackageTypes.includes(packageType); const packageUpdatable = updatablePackageTypes.includes(packageType);
let packageUpdated = false; let packageUpdated = false;
let mainWindow: any = null;
async function checkForUpdates(interval: number) { async function checkForUpdates(interval: number) {
// We use a while loop instead of a setInterval to preserve // We use a while loop instead of a setInterval to preserve
@@ -130,7 +134,7 @@ async function createMainWindow() {
if (fullscreen) { if (fullscreen) {
({ width, height } = electron.screen.getPrimaryDisplay().bounds); ({ width, height } = electron.screen.getPrimaryDisplay().bounds);
} }
const mainWindow = new electron.BrowserWindow({ mainWindow = new electron.BrowserWindow({
width, width,
height, height,
frame: !fullscreen, frame: !fullscreen,
@@ -157,7 +161,6 @@ async function createMainWindow() {
electron.app.setAsDefaultProtocolClient(customProtocol); electron.app.setAsDefaultProtocolClient(customProtocol);
buildWindowMenu(mainWindow);
mainWindow.setFullScreen(true); mainWindow.setFullScreen(true);
// Prevent flash of white when starting the application // Prevent flash of white when starting the application
@@ -240,6 +243,17 @@ async function main(): Promise<void> {
await selectImageURL(await getCommandLineURL(argv)); await selectImageURL(await getCommandLineURL(argv));
}); });
await selectImageURL(await getCommandLineURL(process.argv)); await selectImageURL(await getCommandLineURL(process.argv));
electron.ipcMain.on('change-lng', function (event, args) {
i18n.changeLanguage(args, () => {
console.log('Language changed to: ' + args);
});
if (mainWindow != null) {
buildWindowMenu(mainWindow);
} else {
console.log('Build menu failed. ');
}
});
} }
} }

View File

@@ -17,6 +17,8 @@
import * as electron from 'electron'; import * as electron from 'electron';
import { displayName } from '../../package.json'; import { displayName } from '../../package.json';
import * as i18next from 'i18next';
/** /**
* @summary Builds a native application menu for a given window * @summary Builds a native application menu for a given window
*/ */
@@ -42,12 +44,13 @@ export function buildWindowMenu(window: electron.BrowserWindow) {
const menuTemplate: electron.MenuItemConstructorOptions[] = [ const menuTemplate: electron.MenuItemConstructorOptions[] = [
{ {
role: 'editMenu', role: 'editMenu',
label: i18next.t('menu.edit'),
}, },
{ {
label: 'View', label: i18next.t('menu.view'),
submenu: [ submenu: [
{ {
label: 'Toggle Developer Tools', label: i18next.t('menu.devTool'),
accelerator: accelerator:
process.platform === 'darwin' ? 'Command+Alt+I' : 'Control+Shift+I', process.platform === 'darwin' ? 'Command+Alt+I' : 'Control+Shift+I',
click: toggleDevTools, click: toggleDevTools,
@@ -56,12 +59,14 @@ export function buildWindowMenu(window: electron.BrowserWindow) {
}, },
{ {
role: 'windowMenu', role: 'windowMenu',
label: i18next.t('menu.window'),
}, },
{ {
role: 'help', role: 'help',
label: i18next.t('menu.help'),
submenu: [ submenu: [
{ {
label: 'Etcher Pro', label: i18next.t('menu.pro'),
click() { click() {
electron.shell.openExternal( electron.shell.openExternal(
'https://etcher.io/pro?utm_source=etcher_menu&ref=etcher_menu', 'https://etcher.io/pro?utm_source=etcher_menu&ref=etcher_menu',
@@ -69,13 +74,13 @@ export function buildWindowMenu(window: electron.BrowserWindow) {
}, },
}, },
{ {
label: 'Etcher Website', label: i18next.t('menu.website'),
click() { click() {
electron.shell.openExternal('https://etcher.io?ref=etcher_menu'); electron.shell.openExternal('https://etcher.io?ref=etcher_menu');
}, },
}, },
{ {
label: 'Report an issue', label: i18next.t('menu.issue'),
click() { click() {
electron.shell.openExternal( electron.shell.openExternal(
'https://github.com/balena-io/etcher/issues', 'https://github.com/balena-io/etcher/issues',
@@ -92,25 +97,29 @@ export function buildWindowMenu(window: electron.BrowserWindow) {
submenu: [ submenu: [
{ {
role: 'about' as const, role: 'about' as const,
label: 'About Etcher', label: i18next.t('menu.about'),
}, },
{ {
type: 'separator' as const, type: 'separator' as const,
}, },
{ {
role: 'hide' as const, role: 'hide' as const,
label: i18next.t('menu.hide'),
}, },
{ {
role: 'hideOthers' as const, role: 'hideOthers' as const,
label: i18next.t('menu.hideOthers'),
}, },
{ {
role: 'unhide' as const, role: 'unhide' as const,
label: i18next.t('menu.unhide'),
}, },
{ {
type: 'separator' as const, type: 'separator' as const,
}, },
{ {
role: 'quit' as const, role: 'quit' as const,
label: i18next.t('menu.quit'),
}, },
], ],
}); });

View File

@@ -0,0 +1,21 @@
#!/usr/bin/env osascript -l JavaScript
ObjC.import('stdlib')
const app = Application.currentApplication()
app.includeStandardAdditions = true
const result = app.displayDialog('balenaEtcher 需要来自管理员的权限才能烧录镜像到磁盘。\n\n输入您的密码以允许此操作。', {
defaultAnswer: '',
withIcon: 'caution',
buttons: ['取消', '好'],
defaultButton: '好',
hiddenAnswer: true,
})
if (result.buttonReturned === '好') {
result.textReturned
} else {
$.exit(255)
}

View File

@@ -30,6 +30,9 @@ export async function sudo(
command: string, command: string,
): Promise<{ cancelled: boolean; stdout?: string; stderr?: string }> { ): Promise<{ cancelled: boolean; stdout?: string; stderr?: string }> {
try { try {
let lang = Intl.DateTimeFormat().resolvedOptions().locale;
lang = lang.substr(0, 2);
const { stdout, stderr } = await execFileAsync( const { stdout, stderr } = await execFileAsync(
'sudo', 'sudo',
['--askpass', 'sh', '-c', `echo ${SUCCESSFUL_AUTH_MARKER} && ${command}`], ['--askpass', 'sh', '-c', `echo ${SUCCESSFUL_AUTH_MARKER} && ${command}`],
@@ -40,7 +43,7 @@ export async function sudo(
SUDO_ASKPASS: join( SUDO_ASKPASS: join(
getAppPath(), getAppPath(),
__dirname, __dirname,
'sudo-askpass.osascript.js', 'sudo-askpass.osascript-' + lang + '.js',
), ),
}, },
}, },

View File

@@ -17,16 +17,16 @@
import { Dictionary } from 'lodash'; import { Dictionary } from 'lodash';
import { outdent } from 'outdent'; import { outdent } from 'outdent';
import * as prettyBytes from 'pretty-bytes'; import * as prettyBytes from 'pretty-bytes';
import '../gui/app/i18n';
import * as i18next from 'i18next';
export const progress: Dictionary<(quantity: number) => string> = { export const progress: Dictionary<(quantity: number) => string> = {
successful: (quantity: number) => { successful: (quantity: number) => {
const plural = quantity === 1 ? '' : 's'; return i18next.t('message.flashSucceed', { count: quantity });
return `Successful target${plural}`;
}, },
failed: (quantity: number) => { failed: (quantity: number) => {
const plural = quantity === 1 ? '' : 's'; return i18next.t('message.flashFail', { count: quantity });
return `Failed target${plural}`;
}, },
}; };
@@ -38,129 +38,121 @@ export const info = {
) => { ) => {
const targets = []; const targets = [];
if (failed + successful === 1) { if (failed + successful === 1) {
targets.push(`to ${drive.description} (${drive.displayName})`); targets.push(
i18next.t('message.toDrive', {
description: drive.description,
name: drive.displayName,
}),
);
} else { } else {
if (successful) { if (successful) {
const plural = successful === 1 ? '' : 's'; targets.push(
targets.push(`to ${successful} target${plural}`); i18next.t('message.toTarget', {
count: successful,
num: successful,
}),
);
} }
if (failed) { if (failed) {
const plural = failed === 1 ? '' : 's'; targets.push(
targets.push(`and failed to be flashed to ${failed} target${plural}`); i18next.t('message.andFailTarget', { count: failed, num: failed }),
);
} }
} }
return `${imageBasename} was successfully flashed ${targets.join(' ')}`; return i18next.t('message.succeedTo', {
name: imageBasename,
target: targets.join(' '),
});
}, },
}; };
export const compatibility = { export const compatibility = {
sizeNotRecommended: () => { sizeNotRecommended: () => {
return 'Not recommended'; return i18next.t('message.sizeNotRecommended');
}, },
tooSmall: () => { tooSmall: () => {
return 'Too small'; return i18next.t('message.tooSmall');
}, },
locked: () => { locked: () => {
return 'Locked'; return i18next.t('message.locked');
}, },
system: () => { system: () => {
return 'System drive'; return i18next.t('message.system');
}, },
containsImage: () => { containsImage: () => {
return 'Source drive'; return i18next.t('message.containsImage');
}, },
// The drive is large and therefore likely not a medium you want to write to. // The drive is large and therefore likely not a medium you want to write to.
largeDrive: () => { largeDrive: () => {
return 'Large drive'; return i18next.t('message.largeDrive');
}, },
} as const; } as const;
export const warning = { export const warning = {
tooSmall: (source: { size: number }, target: { size: number }) => { tooSmall: (source: { size: number }, target: { size: number }) => {
return outdent({ newline: ' ' })` return outdent({ newline: ' ' })`
The selected source is ${prettyBytes(source.size - target.size)} ${i18next.t('message.sourceLarger', {
larger than this drive. byte: prettyBytes(source.size - target.size),
})}
`; `;
}, },
exitWhileFlashing: () => { exitWhileFlashing: () => {
return [ return i18next.t('message.exitWhileFlashing');
'You are currently flashing a drive.',
'Closing Etcher may leave your drive in an unusable state.',
].join(' ');
}, },
looksLikeWindowsImage: () => { looksLikeWindowsImage: () => {
return [ return i18next.t('message.looksLikeWindowsImage');
'It looks like you are trying to burn a Windows image.\n\n',
'Unlike other images, Windows images require special processing to be made bootable.',
'We suggest you use a tool specially designed for this purpose, such as',
'<a href="https://rufus.akeo.ie">Rufus</a> (Windows),',
'<a href="https://github.com/slacka/WoeUSB">WoeUSB</a> (Linux),',
'or Boot Camp Assistant (macOS).',
].join(' ');
}, },
missingPartitionTable: () => { missingPartitionTable: () => {
return [ return i18next.t('message.missingPartitionTable', {
'It looks like this is not a bootable image.\n\n', type: i18next.t('message.image'),
'The image does not appear to contain a partition table,', });
'and might not be recognized or bootable by your device.',
].join(' ');
}, },
driveMissingPartitionTable: () => { driveMissingPartitionTable: () => {
return outdent({ newline: ' ' })` return i18next.t('message.missingPartitionTable', {
It looks like this is not a bootable drive. type: i18next.t('message.drive'),
The drive does not appear to contain a partition table, });
and might not be recognized or bootable by your device.
`;
}, },
largeDriveSize: () => { largeDriveSize: () => {
return "This is a large drive! Make sure it doesn't contain files that you want to keep."; return i18next.t('message.largeDriveSize');
}, },
systemDrive: () => { systemDrive: () => {
return 'Selecting your system drive is dangerous and will erase your drive!'; return i18next.t('message.systemDrive');
}, },
sourceDrive: () => { sourceDrive: () => {
return 'Contains the image you chose to flash'; return i18next.t('message.sourceDrive');
}, },
}; };
export const error = { export const error = {
notEnoughSpaceInDrive: () => { notEnoughSpaceInDrive: () => {
return [ return i18next.t('message.noSpace');
'Not enough space on the drive.',
'Please insert larger one and try again.',
].join(' ');
}, },
genericFlashError: (err: Error) => { genericFlashError: (err: Error) => {
return `Something went wrong. If it is a compressed image, please check that the archive is not corrupted.\n${err.message}`; return i18next.t('message.genericFlashError', { error: err.message });
}, },
validation: () => { validation: () => {
return [ return i18next.t('message.validation');
'The write has been completed successfully but Etcher detected potential',
'corruption issues when reading the image back from the drive.',
'\n\nPlease consider writing the image to a different drive.',
].join(' ');
}, },
openSource: (sourceName: string, errorMessage: string) => { openSource: (sourceName: string, errorMessage: string) => {
return outdent` return i18next.t('message.openError', {
Something went wrong while opening ${sourceName} source: sourceName,
error: errorMessage,
Error: ${errorMessage} });
`;
}, },
flashFailure: ( flashFailure: (
@@ -169,35 +161,33 @@ export const error = {
) => { ) => {
const target = const target =
drives.length === 1 drives.length === 1
? `${drives[0].description} (${drives[0].displayName})` ? i18next.t('message.toDrive', {
: `${drives.length} targets`; description: drives[0].description,
return `Something went wrong while writing ${imageBasename} to ${target}.`; name: drives[0].displayName,
})
: i18next.t('message.toTarget', {
count: drives.length,
num: drives.length,
});
return i18next.t('message.flashError', {
image: imageBasename,
targets: target,
});
}, },
driveUnplugged: () => { driveUnplugged: () => {
return [ return i18next.t('message.unplug');
'Looks like Etcher lost access to the drive.',
'Did it get unplugged accidentally?',
"\n\nSometimes this error is caused by faulty readers that don't provide stable access to the drive.",
].join(' ');
}, },
inputOutput: () => { inputOutput: () => {
return [ return i18next.t('message.cannotWrite');
'Looks like Etcher is not able to write to this location of the drive.',
'This error is usually caused by a faulty drive, reader, or port.',
'\n\nPlease try again with another drive, reader, or port.',
].join(' ');
}, },
childWriterDied: () => { childWriterDied: () => {
return [ return i18next.t('message.childWriterDied');
'The writer process ended unexpectedly.',
'Please try again, and contact the Etcher team if the problem persists.',
].join(' ');
}, },
unsupportedProtocol: () => { unsupportedProtocol: () => {
return 'Only http:// and https:// URLs are supported.'; return i18next.t('message.badProtocol');
}, },
}; };

4913
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "balena-etcher", "name": "balena-etcher",
"private": true, "private": true,
"displayName": "balenaEtcher", "displayName": "balenaEtcher",
"version": "1.8.11", "version": "1.13.4",
"packageType": "local", "packageType": "local",
"main": "generated/etcher.js", "main": "generated/etcher.js",
"description": "Flash OS images to SD cards and USB drives, safely and easily.", "description": "Flash OS images to SD cards and USB drives, safely and easily.",
@@ -31,6 +31,7 @@
"test-spectron": "mocha --recursive --reporter spec --require ts-node/register/transpile-only --require-main tests/gui/allow-renderer-process-reuse.ts tests/spectron/runner.spec.ts", "test-spectron": "mocha --recursive --reporter spec --require ts-node/register/transpile-only --require-main tests/gui/allow-renderer-process-reuse.ts tests/spectron/runner.spec.ts",
"test-windows": "npm run lint && npm run test-gui && npm run test-shared && npm run test-spectron && npm run sanity-checks", "test-windows": "npm run lint && npm run test-gui && npm run test-shared && npm run test-spectron && npm run sanity-checks",
"test": "echo npm run test-{linux,windows,macos}", "test": "echo npm run test-{linux,windows,macos}",
"uploadSourcemap": "sentry-cli releases files $npm_config_SENTRY_VERSION upload-sourcemaps ./generated/*.js.map --org $npm_config_SENTRY_ORG --project $npm_config_SENTRY_PROJECT",
"watch": "webpack serve --no-optimization-minimize --config ./webpack.dev.config.ts", "watch": "webpack serve --no-optimization-minimize --config ./webpack.dev.config.ts",
"webpack": "webpack" "webpack": "webpack"
}, },
@@ -52,78 +53,81 @@
"devDependencies": { "devDependencies": {
"@balena/lint": "5.4.2", "@balena/lint": "5.4.2",
"@balena/sudo-prompt": "9.2.1-workaround-windows-amperstand-in-username-0849e215b947987a643fe5763902aea201255534", "@balena/sudo-prompt": "9.2.1-workaround-windows-amperstand-in-username-0849e215b947987a643fe5763902aea201255534",
"@fortawesome/fontawesome-free": "5.13.1", "@fortawesome/fontawesome-free": "5.15.4",
"@sentry/cli": "^2.11.0",
"@svgr/webpack": "5.5.0", "@svgr/webpack": "5.5.0",
"@types/chai": "4.2.7", "@types/chai": "4.3.4",
"@types/copy-webpack-plugin": "6.0.0", "@types/copy-webpack-plugin": "6.4.3",
"@types/mime-types": "2.1.1", "@types/mime-types": "2.1.1",
"@types/mini-css-extract-plugin": "1.2.2", "@types/mini-css-extract-plugin": "1.4.3",
"@types/mocha": "8.0.3", "@types/mocha": "8.2.3",
"@types/node": "14.14.41", "@types/node": "14.18.34",
"@types/node-ipc": "9.1.2", "@types/node-ipc": "9.2.0",
"@types/react": "16.8.5", "@types/react": "16.14.34",
"@types/react-dom": "16.8.4", "@types/react-dom": "16.9.17",
"@types/semver": "7.3.13", "@types/semver": "7.3.13",
"@types/sinon": "9.0.0", "@types/sinon": "9.0.11",
"@types/terser-webpack-plugin": "5.0.2", "@types/terser-webpack-plugin": "5.0.4",
"@types/tmp": "0.2.3", "@types/tmp": "0.2.3",
"@types/webpack-node-externals": "2.5.3", "@types/webpack-node-externals": "2.5.3",
"aws4-axios": "2.4.9", "aws4-axios": "2.4.9",
"chai": "4.2.0", "chai": "4.3.7",
"copy-webpack-plugin": "7.0.0", "copy-webpack-plugin": "7.0.0",
"css-loader": "5.0.1", "css-loader": "5.2.7",
"d3": "4.13.0", "d3": "4.13.0",
"debug": "4.2.0", "debug": "4.3.4",
"electron": "12.2.3", "electron": "^13.5.0",
"electron-builder": "22.10.5", "electron-builder": "^23.0.9",
"electron-mocha": "9.3.3", "electron-mocha": "9.3.3",
"electron-notarize": "1.0.0", "electron-notarize": "1.2.2",
"electron-rebuild": "3.2.9", "electron-rebuild": "3.2.9",
"electron-updater": "4.3.5", "electron-updater": "5.3.0",
"esbuild-loader": "2.16.0", "esbuild-loader": "2.20.0",
"etcher-sdk": "7.4.0", "etcher-sdk": "^7.4.7",
"file-loader": "6.2.0", "file-loader": "6.2.0",
"husky": "4.2.5", "husky": "4.3.8",
"i18next": "21.10.0",
"immutable": "3.8.2", "immutable": "3.8.2",
"lint-staged": "10.2.2", "lint-staged": "10.5.4",
"lodash": "4.17.21", "lodash": "4.17.21",
"mini-css-extract-plugin": "1.3.3", "mini-css-extract-plugin": "1.6.2",
"mocha": "8.0.1", "mocha": "8.4.0",
"native-addon-loader": "2.0.1", "native-addon-loader": "2.0.1",
"node-ipc": "9.1.1", "node-ipc": "9.2.1",
"omit-deep-lodash": "1.1.7", "omit-deep-lodash": "1.1.7",
"outdent": "0.8.0", "outdent": "0.8.0",
"path-is-inside": "1.0.2", "path-is-inside": "1.0.2",
"pnp-webpack-plugin": "1.6.4", "pnp-webpack-plugin": "1.7.0",
"pretty-bytes": "5.3.0", "pretty-bytes": "5.6.0",
"react": "16.8.5", "react": "16.8.5",
"react-dom": "16.8.5", "react-dom": "16.8.5",
"redux": "4.0.5", "react-i18next": "11.18.6",
"rendition": "19.2.0", "redux": "4.2.0",
"rendition": "19.3.2",
"resin-corvus": "2.0.5", "resin-corvus": "2.0.5",
"semver": "7.3.8", "semver": "7.3.8",
"simple-progress-webpack-plugin": "1.1.2", "simple-progress-webpack-plugin": "1.1.2",
"sinon": "9.0.2", "sinon": "9.2.4",
"spectron": "14.0.0", "spectron": "15.0.0",
"string-replace-loader": "3.0.1", "string-replace-loader": "3.1.0",
"style-loader": "2.0.0", "style-loader": "2.0.0",
"styled-components": "5.1.0", "styled-components": "5.3.6",
"sys-class-rgb-led": "3.0.1", "sys-class-rgb-led": "3.0.1",
"terser-webpack-plugin": "5.2.5", "terser-webpack-plugin": "5.3.6",
"ts-loader": "8.0.12", "ts-loader": "8.4.0",
"ts-node": "9.1.1", "ts-node": "9.1.1",
"tslib": "2.0.0", "tslib": "2.4.1",
"typescript": "4.4.4", "typescript": "4.4.4",
"url-loader": "4.1.1", "url-loader": "4.1.1",
"uuid": "8.1.0", "uuid": "8.3.2",
"webpack": "5.11.0", "webpack": "5.75.0",
"webpack-cli": "4.2.0", "webpack-cli": "4.10.0",
"webpack-dev-server": "4.5.0" "webpack-dev-server": "4.11.1"
}, },
"engines": { "engines": {
"node": ">=14 < 16" "node": ">=14 < 16"
}, },
"versionist": { "versionist": {
"publishedAt": "2022-11-08T10:38:47.855Z" "publishedAt": "2023-01-12T15:10:50.986Z"
} }
} }

View File

@@ -1,2 +1,2 @@
awscli==1.11.87 awscli==1.27.28
shyaml==0.5.0 shyaml==0.6.2

View File

@@ -15,7 +15,7 @@
*/ */
import * as CopyPlugin from 'copy-webpack-plugin'; import * as CopyPlugin from 'copy-webpack-plugin';
import { readdirSync } from 'fs'; import { readdirSync, existsSync } from 'fs';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as os from 'os'; import * as os from 'os';
import outdent from 'outdent'; import outdent from 'outdent';
@@ -77,25 +77,45 @@ function renameNodeModules(resourcePath: string) {
); );
} }
function findExt2fsFolder(): string {
const ext2fs = 'node_modules/ext2fs';
const biFsExt2fs = 'node_modules/balena-image-fs/node_modules/ext2fs';
if (existsSync(ext2fs)) {
return ext2fs;
} else if (existsSync(biFsExt2fs)) {
return biFsExt2fs;
} else {
throw Error('ext2fs not found');
}
}
function makeExt2FsRegex(): RegExp {
const folder = findExt2fsFolder();
const libpath = '/lib/libext2fs\\.js$';
return new RegExp(folder.concat(libpath));
}
function findUsbPrebuild(): string[] { function findUsbPrebuild(): string[] {
const usbPrebuildsFolder = path.join('node_modules', 'usb', 'prebuilds') const usbPrebuildsFolder = path.join('node_modules', 'usb', 'prebuilds');
const prebuildFolders = readdirSync(usbPrebuildsFolder); const prebuildFolders = readdirSync(usbPrebuildsFolder);
let bindingFile: string | undefined = 'node.napi.node'; let bindingFile: string | undefined = 'node.napi.node';
const platformFolder = prebuildFolders.find( const platformFolder = prebuildFolders.find(
(f) => (f) => f.startsWith(os.platform()) && f.indexOf(os.arch()) > -1,
f.startsWith(os.platform()) &&
f.indexOf(os.arch()) > -1,
); );
if (platformFolder === undefined) { if (platformFolder === undefined) {
throw new Error('Could not find usb prebuild. Should try fallback to node-gyp and use /build/Release instead of /prebuilds'); throw new Error(
'Could not find usb prebuild. Should try fallback to node-gyp and use /build/Release instead of /prebuilds',
);
} }
const bindingFiles = readdirSync( const bindingFiles = readdirSync(
path.join(usbPrebuildsFolder, platformFolder) path.join(usbPrebuildsFolder, platformFolder),
) );
if (!bindingFiles.length) { if (!bindingFiles.length) {
throw new Error('Could not find usb prebuild for platform') throw new Error('Could not find usb prebuild for platform');
} }
if (bindingFiles.length === 1) { if (bindingFiles.length === 1) {
@@ -107,25 +127,22 @@ function findUsbPrebuild(): string[] {
if (bindingFiles.length > 1) { if (bindingFiles.length > 1) {
bindingFile = bindingFiles.find((file) => { bindingFile = bindingFiles.find((file) => {
if (bindingFiles.indexOf('arm') > -1) { if (bindingFiles.indexOf('arm') > -1) {
const process = require('process') const process = require('process');
return file.indexOf(process.config.variables.arm_version) > -1 return file.indexOf(process.config.variables.arm_version) > -1;
} else { } else {
return file.indexOf('glibc') > -1 return file.indexOf('glibc') > -1;
} }
}) });
} }
if (bindingFile === undefined) { if (bindingFile === undefined) {
throw new Error('Could not find usb prebuild for platform') throw new Error('Could not find usb prebuild for platform');
} }
return [platformFolder, bindingFile]; return [platformFolder, bindingFile];
} }
const [ const [USB_BINDINGS_FOLDER, USB_BINDINGS_FILE] = findUsbPrebuild();
USB_BINDINGS_FOLDER,
USB_BINDINGS_FILE,
] = findUsbPrebuild();
function findLzmaNativeBindingsFolder(): string { function findLzmaNativeBindingsFolder(): string {
const files = readdirSync( const files = readdirSync(
@@ -325,8 +342,8 @@ const commonConfig = {
// Use the libext2fs.wasm file in the generated folder // Use the libext2fs.wasm file in the generated folder
// The way to find the app directory depends on whether we run in the renderer or in the child-writer // The way to find the app directory depends on whether we run in the renderer or in the child-writer
// We use __dirname in the child-writer and electron.remote.app.getAppPath() in the renderer // We use __dirname in the child-writer and electron.remote.app.getAppPath() in the renderer
replace(/node_modules\/ext2fs\/lib\/libext2fs\.js$/, { replace(makeExt2FsRegex(), {
search: 'scriptDirectory=__dirname+"/"', search: 'scriptDirectory = __dirname + "/";',
replace: fetchWasm('ext2fs', 'lib'), replace: fetchWasm('ext2fs', 'lib'),
}), }),
// Same for node-crc-utils // Same for node-crc-utils
@@ -388,7 +405,7 @@ const guiConfigCopyPatterns = [
to: 'modules/node-raspberrypi-usbboot/blobs', to: 'modules/node-raspberrypi-usbboot/blobs',
}, },
{ {
from: 'node_modules/ext2fs/lib/libext2fs.wasm', from: `${findExt2fsFolder()}/lib/libext2fs.wasm`,
to: 'modules/ext2fs/lib/libext2fs.wasm', to: 'modules/ext2fs/lib/libext2fs.wasm',
}, },
{ {
@@ -438,6 +455,7 @@ const guiConfig = {
const mainConfig = { const mainConfig = {
...commonConfig, ...commonConfig,
target: 'electron-main', target: 'electron-main',
devtool: 'source-map',
node: { node: {
__dirname: false, __dirname: false,
__filename: true, __filename: true,