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) => {