diff --git a/lib/gui/app/app.ts b/lib/gui/app/app.ts
index 5fbf9574..27a39734 100644
--- a/lib/gui/app/app.ts
+++ b/lib/gui/app/app.ts
@@ -38,7 +38,7 @@ import * as osDialog from './os/dialog';
import * as windowProgress from './os/window-progress';
import MainPage from './pages/main/MainPage';
import './css/main.css';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
window.addEventListener(
'unhandledrejection',
diff --git a/lib/gui/app/components/drive-selector/drive-selector.tsx b/lib/gui/app/components/drive-selector/drive-selector.tsx
index a4d25cfa..c10413dc 100644
--- a/lib/gui/app/components/drive-selector/drive-selector.tsx
+++ b/lib/gui/app/components/drive-selector/drive-selector.tsx
@@ -44,7 +44,7 @@ import {
import { SourceMetadata } from '../source-selector/source-selector';
import { middleEllipsis } from '../../utils/middle-ellipsis';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
interface UsbbootDrive extends sourceDestination.UsbbootDrive {
progress: number;
diff --git a/lib/gui/app/components/drive-status-warning-modal/drive-status-warning-modal.tsx b/lib/gui/app/components/drive-status-warning-modal/drive-status-warning-modal.tsx
index 2f246da5..d5096b40 100644
--- a/lib/gui/app/components/drive-status-warning-modal/drive-status-warning-modal.tsx
+++ b/lib/gui/app/components/drive-status-warning-modal/drive-status-warning-modal.tsx
@@ -7,7 +7,7 @@ import { middleEllipsis } from '../../utils/middle-ellipsis';
import * as prettyBytes from 'pretty-bytes';
import { DriveWithWarnings } from '../../pages/main/Flash';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
const DriveStatusWarningModal = ({
done,
diff --git a/lib/gui/app/components/flash-another/flash-another.tsx b/lib/gui/app/components/flash-another/flash-another.tsx
index a0cfd43c..c2246317 100644
--- a/lib/gui/app/components/flash-another/flash-another.tsx
+++ b/lib/gui/app/components/flash-another/flash-another.tsx
@@ -17,7 +17,7 @@
import * as React from 'react';
import { BaseButton } from '../../styled-components';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
export interface FlashAnotherProps {
onClick: () => void;
diff --git a/lib/gui/app/components/flash-results/flash-results.tsx b/lib/gui/app/components/flash-results/flash-results.tsx
index 766df43c..99e66937 100644
--- a/lib/gui/app/components/flash-results/flash-results.tsx
+++ b/lib/gui/app/components/flash-results/flash-results.tsx
@@ -31,7 +31,7 @@ import { resetState } from '../../models/flash-state';
import * as selection from '../../models/selection-state';
import { middleEllipsis } from '../../utils/middle-ellipsis';
import { Modal, Table } from '../../styled-components';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
const ErrorsTable = styled((props) =>
{...props} />)`
&&& [data-display='table-head'],
diff --git a/lib/gui/app/components/progress-button/progress-button.tsx b/lib/gui/app/components/progress-button/progress-button.tsx
index c84dfb0d..0986bee6 100644
--- a/lib/gui/app/components/progress-button/progress-button.tsx
+++ b/lib/gui/app/components/progress-button/progress-button.tsx
@@ -20,7 +20,7 @@ import { default as styled } from 'styled-components';
import { fromFlashState } from '../../modules/progress-status';
import { StepButton } from '../../styled-components';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
const FlashProgressBar = styled(ProgressBar)`
> div {
diff --git a/lib/gui/app/components/settings/settings.tsx b/lib/gui/app/components/settings/settings.tsx
index 5618b4a2..f99adea8 100644
--- a/lib/gui/app/components/settings/settings.tsx
+++ b/lib/gui/app/components/settings/settings.tsx
@@ -24,7 +24,7 @@ import * as settings from '../../models/settings';
import * as analytics from '../../modules/analytics';
import { open as openExternal } from '../../os/open-external/services/open-external';
import { Modal } from '../../styled-components';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
interface Setting {
name: string;
diff --git a/lib/gui/app/components/source-selector/source-selector.tsx b/lib/gui/app/components/source-selector/source-selector.tsx
index 6834a2de..46daa029 100644
--- a/lib/gui/app/components/source-selector/source-selector.tsx
+++ b/lib/gui/app/components/source-selector/source-selector.tsx
@@ -66,7 +66,7 @@ import { DriveSelector } from '../drive-selector/drive-selector';
import { DrivelistDrive } from '../../../../shared/drive-constraints';
import axios, { AxiosRequestConfig } from 'axios';
import { isJson } from '../../../../shared/utils';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
const recentUrlImagesKey = 'recentUrlImages';
diff --git a/lib/gui/app/components/target-selector/target-selector-button.tsx b/lib/gui/app/components/target-selector/target-selector-button.tsx
index f8c56b2d..28f14099 100644
--- a/lib/gui/app/components/target-selector/target-selector-button.tsx
+++ b/lib/gui/app/components/target-selector/target-selector-button.tsx
@@ -32,7 +32,7 @@ import {
StepNameButton,
} from '../../styled-components';
import { middleEllipsis } from '../../utils/middle-ellipsis';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
interface TargetSelectorProps {
targets: any[];
diff --git a/lib/gui/app/components/target-selector/target-selector.tsx b/lib/gui/app/components/target-selector/target-selector.tsx
index 767cebc1..965db59f 100644
--- a/lib/gui/app/components/target-selector/target-selector.tsx
+++ b/lib/gui/app/components/target-selector/target-selector.tsx
@@ -37,7 +37,7 @@ import TgtSvg from '../../../assets/tgt.svg';
import DriveSvg from '../../../assets/drive.svg';
import { warning } from '../../../../shared/messages';
import { DrivelistDrive } from '../../../../shared/drive-constraints';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
export const getDriveListLabel = () => {
return getSelectedDrives()
diff --git a/lib/gui/app/i18n.ts b/lib/gui/app/i18n.ts
index c7c7e83a..78ec6225 100644
--- a/lib/gui/app/i18n.ts
+++ b/lib/gui/app/i18n.ts
@@ -1,10 +1,15 @@
-import i18next from 'i18next';
+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)) {
diff --git a/lib/gui/app/i18n/en.ts b/lib/gui/app/i18n/en.ts
index aaeb2631..d6e37eee 100644
--- a/lib/gui/app/i18n/en.ts
+++ b/lib/gui/app/i18n/en.ts
@@ -17,7 +17,7 @@ const translation = {
decompressing: 'Decompressing...',
flashing: 'Flashing...',
finishing: 'Finishing...',
- verifying: 'Verifying...',
+ verifying: 'Validating...',
failing: 'Failed',
},
message: {
@@ -32,15 +32,12 @@ const translation = {
flashSucceed_other: 'Successful targets',
flashFail_one: 'Failed target',
flashFail_other: 'Failed targets',
- to: 'to ',
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',
- target_one: ' target',
- target_other: ' targets',
- succeedTo: '{{name}} was successfully flashed to {{target}}',
+ succeedTo: '{{name}} was successfully flashed {{target}}',
exitWhileFlashing:
'You are currently flashing a drive. Closing Etcher may leave your drive in an unusable state.',
looksLikeWindowsImage:
@@ -62,8 +59,7 @@ const translation = {
'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}} to {{targets}}.',
+ 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:
@@ -129,6 +125,8 @@ const translation = {
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.',
diff --git a/lib/gui/app/i18n/zh-CN.ts b/lib/gui/app/i18n/zh-CN.ts
index 7a370359..f458653a 100644
--- a/lib/gui/app/i18n/zh-CN.ts
+++ b/lib/gui/app/i18n/zh-CN.ts
@@ -32,15 +32,12 @@ const translation = {
flashSucceed_other: '烧录成功',
flashFail_one: '烧录失败',
flashFail_other: '烧录失败',
- to: '到 ',
toDrive: '到 {{description}} ({{name}})',
toTarget_one: '到 {{num}} 个目标',
toTarget_other: '到 {{num}} 个目标',
andFailTarget_one: '并烧录失败了 {{num}} 个目标',
andFailTarget_other: '并烧录失败了 {{num}} 个目标',
- target_one: ' 个目标',
- target_other: ' 个目标',
- succeedTo: '{{name}} 被成功烧录到 {{target}}',
+ succeedTo: '{{name}} 被成功烧录 {{target}}',
exitWhileFlashing:
'您当前正在刷机。 关闭 Etcher 可能会导致您的磁盘无法使用。',
looksLikeWindowsImage:
@@ -58,7 +55,7 @@ const translation = {
validation:
'写入已成功完成,但 Etcher 在从磁盘读取镜像时检测到潜在的损坏问题。 \n\n请考虑将镜像写入其他磁盘。',
openError: '打开 {{source}} 时出错。\n\n错误信息: {{error}}',
- flashError: '烧录 {{image}} 到 {{targets}} 失败。',
+ flashError: '烧录 {{image}} {{targets}} 失败。',
unplug:
'看起来 Etcher 失去了对磁盘的连接。 它是不是被意外拔掉了?\n\n有时这个错误是因为读卡器出了故障。',
cannotWrite:
@@ -134,8 +131,10 @@ const translation = {
skip: '跳过了验证',
moreInfo: '更多信息',
speedTip:
- '通过将图像大小除以烧录时间来计算速度。\n由于我们能够跳过未使用的部分,因此具有EXT分区的磁盘镜像烧录速度更快。',
+ '通过将镜像大小除以烧录时间来计算速度。\n由于我们能够跳过未使用的部分,因此具有EXT分区的磁盘镜像烧录速度更快。',
speed: '速度:{{speed}} MB/秒',
+ speedShort: '{{speed}} MB/秒',
+ eta: '预计还需要:{{eta}}',
failedTarget: '失败的烧录目标',
failedRetry: '重试烧录失败目标',
flashFailed: '烧录失败。',
diff --git a/lib/gui/app/i18n/zh-TW.ts b/lib/gui/app/i18n/zh-TW.ts
index 3ad8be83..f9957e20 100644
--- a/lib/gui/app/i18n/zh-TW.ts
+++ b/lib/gui/app/i18n/zh-TW.ts
@@ -32,15 +32,12 @@ const translation = {
flashSucceed_other: '燒錄成功',
flashFail_one: '燒錄失敗',
flashFail_other: '燒錄失敗',
- to: '到 ',
toDrive: '到 {{description}} ({{name}})',
toTarget_one: '到 {{num}} 個目標',
toTarget_other: '到 {{num}} 個目標',
andFailTarget_one: '並燒錄失敗了 {{num}} 個目標',
andFailTarget_other: '並燒錄失敗了 {{num}} 個目標',
- target_one: ' 個目標',
- target_other: ' 個目標',
- succeedTo: '{{name}} 被成功燒錄到 {{target}}',
+ succeedTo: '{{name}} 被成功燒錄 {{target}}',
exitWhileFlashing:
'您當前正在刷機。 關閉 Etcher 可能會導致您的磁盤無法使用。',
looksLikeWindowsImage:
@@ -58,7 +55,7 @@ const translation = {
validation:
'寫入已成功完成,但 Etcher 在從磁盤讀取鏡像時檢測到潛在的損壞問題。 \n\n請考慮將鏡像寫入其他磁盤。',
openError: '打開 {{source}} 時出錯。\n\n錯誤信息: {{error}}',
- flashError: '燒錄 {{image}} 到 {{targets}} 失敗。',
+ flashError: '燒錄 {{image}} {{targets}} 失敗。',
unplug:
'看起來 Etcher 失去了對磁盤的連接。 它是不是被意外拔掉了?\n\n有時這個錯誤是因爲讀卡器出了故障。',
cannotWrite:
@@ -134,8 +131,10 @@ const translation = {
skip: '跳過了驗證',
moreInfo: '更多信息',
speedTip:
- '通過將圖像大小除以燒錄時間來計算速度。\n由於我們能夠跳過未使用的部分,因此具有EXT分區的磁盤鏡像燒錄速度更快。',
+ '通過將鏡像大小除以燒錄時間來計算速度。\n由於我們能夠跳過未使用的部分,因此具有EXT分區的磁盤鏡像燒錄速度更快。',
speed: '速度:{{speed}} MB/秒',
+ speedShort: '{{speed}} MB/秒',
+ eta: '預計還需要:{{eta}}',
failedTarget: '失敗的燒錄目標',
failedRetry: '重試燒錄失敗目標',
flashFailed: '燒錄失敗。',
diff --git a/lib/gui/app/modules/progress-status.ts b/lib/gui/app/modules/progress-status.ts
index 1a05e8e7..32d492d9 100644
--- a/lib/gui/app/modules/progress-status.ts
+++ b/lib/gui/app/modules/progress-status.ts
@@ -15,7 +15,7 @@
*/
import * as prettyBytes from 'pretty-bytes';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
export interface FlashState {
active: number;
diff --git a/lib/gui/app/os/dialog.ts b/lib/gui/app/os/dialog.ts
index a55113ea..0fbe4883 100644
--- a/lib/gui/app/os/dialog.ts
+++ b/lib/gui/app/os/dialog.ts
@@ -20,7 +20,7 @@ import * as _ from 'lodash';
import * as errors from '../../../shared/errors';
import * as settings from '../../../gui/app/models/settings';
import { SUPPORTED_EXTENSIONS } from '../../../shared/supported-formats';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
async function mountSourceDrive() {
// sourceDrivePath is the name of the link in /dev/disk/by-path
diff --git a/lib/gui/app/pages/main/Flash.tsx b/lib/gui/app/pages/main/Flash.tsx
index 4fc526ca..53d20c89 100644
--- a/lib/gui/app/pages/main/Flash.tsx
+++ b/lib/gui/app/pages/main/Flash.tsx
@@ -37,6 +37,7 @@ import {
import FlashSvg from '../../../assets/flash.svg';
import DriveStatusWarningModal from '../../components/drive-status-warning-modal/drive-status-warning-modal';
+import * as i18next from 'i18next';
const COMPLETED_PERCENTAGE = 100;
const SPEED_PRECISION = 2;
@@ -293,9 +294,17 @@ export class FlashStep extends React.PureComponent<
color="#7e8085"
width="100%"
>
- {this.props.speed.toFixed(SPEED_PRECISION)} MB/s
+
+ {i18next.t('flash.speedShort', {
+ speed: this.props.speed.toFixed(SPEED_PRECISION),
+ })}
+
{!_.isNil(this.props.eta) && (
- ETA: {formatSeconds(this.props.eta)}
+
+ {i18next.t('flash.eta', {
+ eta: formatSeconds(this.props.eta),
+ })}
+
)}
)}
diff --git a/lib/gui/menu.ts b/lib/gui/menu.ts
index 8580b2c2..e6e30e68 100644
--- a/lib/gui/menu.ts
+++ b/lib/gui/menu.ts
@@ -17,7 +17,7 @@
import * as electron from 'electron';
import { displayName } from '../../package.json';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
/**
* @summary Builds a native application menu for a given window
diff --git a/lib/shared/messages.ts b/lib/shared/messages.ts
index 8f9e4a41..090b8836 100644
--- a/lib/shared/messages.ts
+++ b/lib/shared/messages.ts
@@ -18,7 +18,7 @@ import { Dictionary } from 'lodash';
import { outdent } from 'outdent';
import * as prettyBytes from 'pretty-bytes';
import '../gui/app/i18n';
-import i18next from 'i18next';
+import * as i18next from 'i18next';
export const progress: Dictionary<(quantity: number) => string> = {
successful: (quantity: number) => {