mirror of
https://github.com/stablyai/orca.git
synced 2026-11-03 02:27:43 +00:00
fix(i18n): translate updater failure messages shown in the renderer (#35833)
* fix(i18n): translate updater failure messages shown in the renderer * fix(i18n): localize the dev-channel platform list and paired-server updater errors * fix(i18n): sync runtime catalog and coded updater status expectations --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
@@ -6,22 +6,14 @@ import {
|
||||
} from './linux-package-update-recovery'
|
||||
import { getLinuxPackageType } from './linux-update-package-type'
|
||||
import type { LinuxPackageArtifact } from './linux-package-update-recovery'
|
||||
|
||||
export const LINUX_PACKAGE_MARKER_UNUSABLE_MESSAGE =
|
||||
'Orca could not verify the installed Linux package format, so it will not install this update automatically. Download the update from the official release page and install it manually.'
|
||||
export const LINUX_PACKAGE_EXTERNALLY_MANAGED_MESSAGE =
|
||||
'This copy of Orca is managed by your system package manager, so Orca cannot install updates itself. Update Orca through your distribution instead.'
|
||||
export const LINUX_PACKAGE_MANUAL_INSTALL_MESSAGE =
|
||||
'Quit Orca before running the system package install command.'
|
||||
const PACKAGE_METADATA_UNUSABLE_MESSAGE =
|
||||
'The downloaded package metadata could not be verified. Quit Orca before downloading and installing the update from the official release page.'
|
||||
import { updaterCodedMessage } from '../shared/updater-failure-copy'
|
||||
|
||||
export function createLinuxPackageManualInstallStatus(
|
||||
artifact: Pick<LinuxPackageArtifact, 'packageType' | 'version'>
|
||||
): UpdateStatus {
|
||||
return {
|
||||
state: 'error',
|
||||
message: LINUX_PACKAGE_MANUAL_INSTALL_MESSAGE,
|
||||
...updaterCodedMessage('linuxPackageManualInstall'),
|
||||
recovery: {
|
||||
kind: 'linux-package-install',
|
||||
packageType: artifact.packageType,
|
||||
@@ -70,7 +62,7 @@ export function resolveLinuxPackageDownloadedStatus(info: {
|
||||
clearTrackedLinuxPackageArtifact()
|
||||
return {
|
||||
state: 'error',
|
||||
message: LINUX_PACKAGE_MARKER_UNUSABLE_MESSAGE,
|
||||
...updaterCodedMessage('linuxPackageMarkerUnusable'),
|
||||
version: info.version,
|
||||
retryable: false
|
||||
}
|
||||
@@ -79,7 +71,7 @@ export function resolveLinuxPackageDownloadedStatus(info: {
|
||||
if (!artifact) {
|
||||
return {
|
||||
state: 'error',
|
||||
message: PACKAGE_METADATA_UNUSABLE_MESSAGE,
|
||||
...updaterCodedMessage('linuxPackageMetadataUnusable'),
|
||||
version: info.version,
|
||||
retryable: false
|
||||
}
|
||||
|
||||
@@ -198,6 +198,7 @@ describe('registerAutoUpdaterHandlers linux package artifact tracking', () => {
|
||||
expect(context.sendStatus).toHaveBeenLastCalledWith({
|
||||
state: 'error',
|
||||
message: 'Quit Orca before running the system package install command.',
|
||||
messageCode: 'linuxPackageManualInstall',
|
||||
recovery: {
|
||||
kind: 'linux-package-install',
|
||||
packageType,
|
||||
@@ -220,6 +221,7 @@ describe('registerAutoUpdaterHandlers linux package artifact tracking', () => {
|
||||
state: 'error',
|
||||
message:
|
||||
'The downloaded package metadata could not be verified. Quit Orca before downloading and installing the update from the official release page.',
|
||||
messageCode: 'linuxPackageMetadataUnusable',
|
||||
version: '1.0.61',
|
||||
retryable: false
|
||||
}
|
||||
@@ -261,6 +263,7 @@ describe('registerAutoUpdaterHandlers linux package artifact tracking', () => {
|
||||
state: 'error',
|
||||
message:
|
||||
'Orca could not verify the installed Linux package format, so it will not install this update automatically. Download the update from the official release page and install it manually.',
|
||||
messageCode: 'linuxPackageMarkerUnusable',
|
||||
version: '1.0.61',
|
||||
retryable: false
|
||||
})
|
||||
@@ -292,6 +295,7 @@ describe('registerAutoUpdaterHandlers linux package artifact tracking', () => {
|
||||
expect(context.sendStatus).toHaveBeenLastCalledWith({
|
||||
state: 'error',
|
||||
message: 'Quit Orca before running the system package install command.',
|
||||
messageCode: 'linuxPackageManualInstall',
|
||||
recovery: {
|
||||
kind: 'linux-package-install',
|
||||
packageType: 'deb',
|
||||
@@ -314,6 +318,7 @@ describe('registerAutoUpdaterHandlers linux package artifact tracking', () => {
|
||||
expect(context.sendStatus).toHaveBeenLastCalledWith({
|
||||
state: 'error',
|
||||
message: 'Quit Orca before running the system package install command.',
|
||||
messageCode: 'linuxPackageManualInstall',
|
||||
recovery: {
|
||||
kind: 'linux-package-install',
|
||||
packageType: 'deb',
|
||||
@@ -391,6 +396,7 @@ describe('registerAutoUpdaterHandlers linux package artifact tracking', () => {
|
||||
expect(context.sendStatus).toHaveBeenLastCalledWith({
|
||||
state: 'error',
|
||||
message: 'Quit Orca before running the system package install command.',
|
||||
messageCode: 'linuxPackageManualInstall',
|
||||
recovery: {
|
||||
kind: 'linux-package-install',
|
||||
packageType: 'deb',
|
||||
@@ -446,6 +452,7 @@ describe('registerAutoUpdaterHandlers linux package artifact tracking', () => {
|
||||
expect(context.sendStatus).toHaveBeenLastCalledWith({
|
||||
state: 'error',
|
||||
message: 'Quit Orca before running the system package install command.',
|
||||
messageCode: 'linuxPackageManualInstall',
|
||||
recovery: {
|
||||
kind: 'linux-package-install',
|
||||
packageType: 'deb',
|
||||
|
||||
@@ -108,6 +108,7 @@ const ARTIFACT = {
|
||||
const MANUAL_INSTALL_STATUS = {
|
||||
state: 'error',
|
||||
message: 'Quit Orca before running the system package install command.',
|
||||
messageCode: 'linuxPackageManualInstall',
|
||||
recovery: {
|
||||
kind: 'linux-package-install',
|
||||
packageType: 'deb',
|
||||
|
||||
@@ -22,7 +22,7 @@ vi.mock('./git/gh-rate-limit-breaker', () => ({
|
||||
recordGhPrimaryRateLimit: (...args: unknown[]) => recordRateLimitMock(...args)
|
||||
}))
|
||||
|
||||
const { describeRateLimitReset, listReleaseBuilds, rateLimitResetAtMs, resolveTargetBuild } =
|
||||
const { listReleaseBuilds, rateLimitResetAtMs, resolveTargetBuild } =
|
||||
await import('./updater-release-builds')
|
||||
|
||||
function jsonResponse(
|
||||
@@ -396,9 +396,13 @@ describe('listReleaseBuilds', () => {
|
||||
})
|
||||
)
|
||||
|
||||
await expect(listReleaseBuilds('hourly', 'darwin')).rejects.toThrow(
|
||||
const failure = listReleaseBuilds('hourly', 'darwin')
|
||||
await expect(failure).rejects.toThrow(
|
||||
"GitHub rate limit reached. Try again in about 28 minutes, or run `gh auth login` so Orca can use your account's higher limit."
|
||||
)
|
||||
await expect(failure).rejects.toMatchObject({
|
||||
coded: { messageCode: 'rateLimitedInMinutesSignedOut', messageParams: { count: 28 } }
|
||||
})
|
||||
})
|
||||
|
||||
it('omits the sign-in hint when the rate-limited request was authenticated', async () => {
|
||||
@@ -407,9 +411,9 @@ describe('listReleaseBuilds', () => {
|
||||
jsonResponse(null, { ok: false, status: 403, headers: { 'x-ratelimit-remaining': '0' } })
|
||||
)
|
||||
|
||||
const failure = listReleaseBuilds('hourly', 'darwin')
|
||||
await expect(failure).rejects.toThrow(/rate limit reached/)
|
||||
await expect(failure).rejects.not.toThrow(/gh auth login/)
|
||||
await expect(listReleaseBuilds('hourly', 'darwin')).rejects.toThrow(
|
||||
/^GitHub rate limit reached\. Try again in a few minutes\.$/
|
||||
)
|
||||
})
|
||||
|
||||
it('treats 429 as a rate limit', async () => {
|
||||
@@ -464,22 +468,6 @@ describe('rateLimitResetAtMs', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('describeRateLimitReset', () => {
|
||||
const nowMs = 1_800_000_000_000
|
||||
|
||||
it('falls back to a vague wait when the reset is unknown', () => {
|
||||
expect(describeRateLimitReset(null, nowMs)).toBe('in a few minutes')
|
||||
})
|
||||
|
||||
it('rounds a sub-minute reset up to a minute', () => {
|
||||
expect(describeRateLimitReset(nowMs + 20_000, nowMs)).toBe('in about a minute')
|
||||
})
|
||||
|
||||
it('rounds a partial minute up', () => {
|
||||
expect(describeRateLimitReset(nowMs + 9 * 60_000 + 1, nowMs)).toBe('in about 10 minutes')
|
||||
})
|
||||
})
|
||||
|
||||
describe('resolveTargetBuild', () => {
|
||||
it('pins an hourly tag at the hourly repo download path', () => {
|
||||
expect(resolveTargetBuild('hourly', 'v1.4.160-hourly.202607281400')).toEqual({
|
||||
|
||||
@@ -13,6 +13,7 @@ import { parseRetryAfterHeaderMs } from '../shared/retry-after-header'
|
||||
import { getGhRateLimitBlockedUntilMs, recordGhPrimaryRateLimit } from './git/gh-rate-limit-breaker'
|
||||
import { isValidVersion } from './updater-fallback'
|
||||
import { rejectReleaseApiToken, resolveReleaseApiToken } from './updater-release-api-token'
|
||||
import { UpdaterCodedError } from './updater/updater-coded-error'
|
||||
|
||||
const FETCH_TIMEOUT_MS = 8000
|
||||
const MAX_LISTED_BUILDS = 100
|
||||
@@ -60,12 +61,18 @@ export function rateLimitResetAtMs(headers: Headers, nowMs: number): number | nu
|
||||
return resetEpochSeconds > 0 ? resetEpochSeconds * 1000 : null
|
||||
}
|
||||
|
||||
export function describeRateLimitReset(resetAtMs: number | null, nowMs: number): string {
|
||||
function rateLimitError(resetAtMs: number | null, nowMs: number, signedIn: boolean): Error {
|
||||
if (resetAtMs === null) {
|
||||
return 'in a few minutes'
|
||||
return new UpdaterCodedError(signedIn ? 'rateLimitedSoon' : 'rateLimitedSoonSignedOut')
|
||||
}
|
||||
const minutes = Math.ceil((resetAtMs - nowMs) / 60_000)
|
||||
return minutes <= 1 ? 'in about a minute' : `in about ${minutes} minutes`
|
||||
if (minutes <= 1) {
|
||||
return new UpdaterCodedError(signedIn ? 'rateLimitedInMinute' : 'rateLimitedInMinuteSignedOut')
|
||||
}
|
||||
return new UpdaterCodedError(
|
||||
signedIn ? 'rateLimitedInMinutes' : 'rateLimitedInMinutesSignedOut',
|
||||
{ count: minutes }
|
||||
)
|
||||
}
|
||||
|
||||
function releaseListError(
|
||||
@@ -75,18 +82,13 @@ function releaseListError(
|
||||
signedIn: boolean
|
||||
): Error {
|
||||
if (res.status === 404) {
|
||||
return new Error(`No releases repository found at ${repo}.`)
|
||||
return new UpdaterCodedError('releaseRepoNotFound', { repo })
|
||||
}
|
||||
if (isRateLimited(res)) {
|
||||
const nowMs = Date.now()
|
||||
const retry = describeRateLimitReset(rateLimitResetAtMs(res.headers, nowMs), nowMs)
|
||||
return new Error(
|
||||
signedIn
|
||||
? `GitHub rate limit reached. Try again ${retry}.`
|
||||
: `GitHub rate limit reached. Try again ${retry}, or run \`gh auth login\` so Orca can use your account's higher limit.`
|
||||
)
|
||||
return rateLimitError(rateLimitResetAtMs(res.headers, nowMs), nowMs, signedIn)
|
||||
}
|
||||
return new Error(`Could not list ${channel} builds (HTTP ${res.status}).`)
|
||||
return new UpdaterCodedError('releaseListFailed', { channel, status: res.status })
|
||||
}
|
||||
|
||||
export function getReleaseDownloadUrlForRepo(repo: string, tag: string): string {
|
||||
@@ -180,7 +182,7 @@ export async function listReleaseBuilds(
|
||||
}
|
||||
const payload: unknown = await res.json()
|
||||
if (!Array.isArray(payload)) {
|
||||
throw new Error(`Could not read the ${channel} release list.`)
|
||||
throw new UpdaterCodedError('releaseListUnreadable', { channel })
|
||||
}
|
||||
const builds = payload
|
||||
.map((entry) => parseReleaseEntry(entry as GitHubReleaseEntry, repo, platform))
|
||||
@@ -198,7 +200,7 @@ export type ResolvedTargetBuild = {
|
||||
export function resolveTargetBuild(channel: ReleaseChannel, tag: string): ResolvedTargetBuild {
|
||||
const version = normalizeTagToVersion(tag)
|
||||
if (!isValidVersion(version)) {
|
||||
throw new Error(`"${tag}" is not a valid release tag.`)
|
||||
throw new UpdaterCodedError('invalidReleaseTag', { tag })
|
||||
}
|
||||
const repo = getReleaseRepoForChannel(channel)
|
||||
return { tag, version, feedUrl: getReleaseDownloadUrlForRepo(repo, tag) }
|
||||
|
||||
@@ -67,6 +67,8 @@ describe('updater', () => {
|
||||
expect(send).toHaveBeenCalledWith('updater:status', {
|
||||
state: 'error',
|
||||
message,
|
||||
messageCode: 'channelUnsupportedPlatform',
|
||||
messageParams: { channel: expect.any(String) },
|
||||
userInitiated: true
|
||||
})
|
||||
expect(autoUpdaterMock.checkForUpdates).not.toHaveBeenCalled()
|
||||
@@ -92,6 +94,8 @@ describe('updater', () => {
|
||||
expect(send).toHaveBeenCalledWith('updater:status', {
|
||||
state: 'error',
|
||||
message: expect.stringContaining('Download the installer from the release page'),
|
||||
messageCode: 'unsignedDevChannel',
|
||||
messageParams: { channel: 'Adhoc' },
|
||||
userInitiated: true
|
||||
})
|
||||
expect(autoUpdaterMock.checkForUpdates).not.toHaveBeenCalled()
|
||||
@@ -118,11 +122,13 @@ describe('updater', () => {
|
||||
|
||||
checkForUpdatesFromMenu({ channel, targetTag })
|
||||
|
||||
expect(send).not.toHaveBeenCalledWith('updater:status', {
|
||||
state: 'error',
|
||||
message: expect.stringContaining('Download the installer'),
|
||||
userInitiated: true
|
||||
})
|
||||
expect(send).not.toHaveBeenCalledWith(
|
||||
'updater:status',
|
||||
expect.objectContaining({
|
||||
state: 'error',
|
||||
message: expect.stringContaining('Download the installer')
|
||||
})
|
||||
)
|
||||
expect(autoUpdaterMock.allowDowngrade).toBe(true)
|
||||
} finally {
|
||||
platformSpy.mockRestore()
|
||||
@@ -553,6 +559,7 @@ describe('updater', () => {
|
||||
expect(sendMock).toHaveBeenCalledWith('updater:status', {
|
||||
state: 'error',
|
||||
message: "Couldn't reach the update server. Try again in a few minutes.",
|
||||
messageCode: 'updateServerUnreachable',
|
||||
userInitiated: true
|
||||
})
|
||||
})
|
||||
@@ -586,6 +593,7 @@ describe('updater', () => {
|
||||
expect(sendMock).toHaveBeenCalledWith('updater:status', {
|
||||
state: 'error',
|
||||
message: "Couldn't reach the update server. Try again in a few minutes.",
|
||||
messageCode: 'updateServerUnreachable',
|
||||
userInitiated: true
|
||||
})
|
||||
})
|
||||
|
||||
@@ -288,6 +288,7 @@ describe('updater check failure handling', () => {
|
||||
expect(sendMock).toHaveBeenCalledWith('updater:status', {
|
||||
state: 'error',
|
||||
message: RELEASE_NOT_READY_MESSAGE,
|
||||
messageCode: 'releaseNotReady',
|
||||
userInitiated: true
|
||||
})
|
||||
})
|
||||
|
||||
@@ -99,6 +99,7 @@ describe('updater externally managed Linux installs', () => {
|
||||
expect(lastStatus(send)).toEqual({
|
||||
state: 'error',
|
||||
message: EXTERNALLY_MANAGED_MESSAGE,
|
||||
messageCode: 'linuxPackageExternallyManaged',
|
||||
version: '1.0.61',
|
||||
retryable: false
|
||||
})
|
||||
|
||||
@@ -114,6 +114,7 @@ describe('updater Linux root packages', () => {
|
||||
expect(lastStatus(send)).toEqual({
|
||||
state: 'error',
|
||||
message: 'Quit Orca before running the system package install command.',
|
||||
messageCode: 'linuxPackageManualInstall',
|
||||
recovery: {
|
||||
kind: 'linux-package-install',
|
||||
packageType,
|
||||
@@ -229,6 +230,7 @@ describe('updater Linux root packages', () => {
|
||||
state: 'error',
|
||||
message:
|
||||
'Orca could not verify the installed Linux package format, so it will not install this update automatically. Download the update from the official release page and install it manually.',
|
||||
messageCode: 'linuxPackageMarkerUnusable',
|
||||
version: '1.0.61',
|
||||
retryable: false
|
||||
})
|
||||
|
||||
@@ -105,6 +105,7 @@ describe('updater', () => {
|
||||
expect(statuses).toContainEqual({
|
||||
state: 'error',
|
||||
message: "Couldn't reach the update server. Try again in a few minutes.",
|
||||
messageCode: 'updateServerUnreachable',
|
||||
userInitiated: true
|
||||
})
|
||||
})
|
||||
@@ -196,6 +197,7 @@ describe('updater', () => {
|
||||
expect(statuses).toContainEqual({
|
||||
state: 'error',
|
||||
message: "Couldn't reach the update server. Try again in a few minutes.",
|
||||
messageCode: 'updateServerUnreachable',
|
||||
userInitiated: true
|
||||
})
|
||||
})
|
||||
@@ -347,6 +349,7 @@ describe('updater', () => {
|
||||
expect(statuses.at(-1)).toEqual({
|
||||
state: 'error',
|
||||
message: "Couldn't reach the update server. Try again in a few minutes.",
|
||||
messageCode: 'updateServerUnreachable',
|
||||
userInitiated: true
|
||||
})
|
||||
})
|
||||
@@ -447,6 +450,7 @@ describe('updater', () => {
|
||||
expect(statuses).toContainEqual({
|
||||
state: 'error',
|
||||
message: "Couldn't reach the update server. Try again in a few minutes.",
|
||||
messageCode: 'updateServerUnreachable',
|
||||
userInitiated: true
|
||||
})
|
||||
})
|
||||
@@ -661,6 +665,7 @@ describe('updater', () => {
|
||||
expect(statuses).toContainEqual({
|
||||
state: 'error',
|
||||
message: "Couldn't reach the update server. Try again in a few minutes.",
|
||||
messageCode: 'updateServerUnreachable',
|
||||
userInitiated: true
|
||||
})
|
||||
})
|
||||
|
||||
@@ -127,6 +127,7 @@ describe('updater', () => {
|
||||
expect(sendMock).toHaveBeenCalledWith('updater:status', {
|
||||
state: 'error',
|
||||
message: "Couldn't reach the update server. Try again in a few minutes.",
|
||||
messageCode: 'updateServerUnreachable',
|
||||
userInitiated: true
|
||||
})
|
||||
})
|
||||
@@ -182,6 +183,7 @@ describe('updater', () => {
|
||||
expect(sendMock).toHaveBeenCalledWith('updater:status', {
|
||||
state: 'error',
|
||||
message: "Couldn't reach the update server. Try again in a few minutes.",
|
||||
messageCode: 'updateServerUnreachable',
|
||||
userInitiated: true
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { app } from 'electron'
|
||||
import {
|
||||
DEV_CHANNEL_PLATFORM_LABEL,
|
||||
getVersionChannel,
|
||||
hasDedicatedReleaseRepo,
|
||||
isChannelSupportedOnPlatform,
|
||||
@@ -14,6 +13,8 @@ import { profileStateBuildCompatibilityError } from '../../shared/profile-state-
|
||||
import { listReleaseBuilds, resolveTargetBuild } from '../updater-release-builds'
|
||||
import { ReleaseBuildListCache, type ReleaseBuildListOptions } from '../updater-release-build-cache'
|
||||
import { UpdaterMenuChecks } from './updater-menu-checks'
|
||||
import { updaterCodedMessage } from '../../shared/updater-failure-copy'
|
||||
import { updaterErrorMessage } from './updater-coded-error'
|
||||
|
||||
export abstract class UpdaterBuildSelection extends UpdaterMenuChecks {
|
||||
private readonly releaseBuildCache = new ReleaseBuildListCache((channel) =>
|
||||
@@ -96,7 +97,9 @@ export abstract class UpdaterBuildSelection extends UpdaterMenuChecks {
|
||||
if (!isChannelSupportedOnPlatform(channel, process.platform)) {
|
||||
this.sendStatus({
|
||||
state: 'error',
|
||||
message: `${RELEASE_CHANNEL_LABELS[channel]} builds are produced only for ${DEV_CHANNEL_PLATFORM_LABEL}.`,
|
||||
...updaterCodedMessage('channelUnsupportedPlatform', {
|
||||
channel: RELEASE_CHANNEL_LABELS[channel]
|
||||
}),
|
||||
userInitiated: true
|
||||
})
|
||||
return
|
||||
@@ -111,7 +114,7 @@ export abstract class UpdaterBuildSelection extends UpdaterMenuChecks {
|
||||
) {
|
||||
this.sendStatus({
|
||||
state: 'error',
|
||||
message: `${RELEASE_CHANNEL_LABELS[channel]} builds are unsigned, and this signed build only installs updates signed by Orca's publisher. Download the installer from the release page and run it once — updates work normally from there, including back to Stable.`,
|
||||
...updaterCodedMessage('unsignedDevChannel', { channel: RELEASE_CHANNEL_LABELS[channel] }),
|
||||
userInitiated: true
|
||||
})
|
||||
return
|
||||
@@ -164,7 +167,7 @@ export abstract class UpdaterBuildSelection extends UpdaterMenuChecks {
|
||||
this.restoreReleaseUpdateSource()
|
||||
this.sendSettledCheckStatus({
|
||||
state: 'error',
|
||||
message: String((error as Error)?.message ?? error),
|
||||
...updaterErrorMessage(error),
|
||||
userInitiated: true
|
||||
})
|
||||
} finally {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { isBenignCheckFailure } from '../updater-fallback'
|
||||
import { ReleaseFeedPreflightError } from './updater-state'
|
||||
import type { CheckFailureSource } from './updater-state'
|
||||
import { UpdaterReleaseFeed } from './updater-release-feed'
|
||||
import { updaterCodedMessage } from '../../shared/updater-failure-copy'
|
||||
|
||||
export abstract class UpdaterCheckFailure extends UpdaterReleaseFeed {
|
||||
protected isRetryableReleaseFeedPreflightFailure(sourceError: unknown): boolean {
|
||||
@@ -81,9 +82,11 @@ export abstract class UpdaterCheckFailure extends UpdaterReleaseFeed {
|
||||
// User clicks need visible feedback distinguishing incomplete releases from transport failure.
|
||||
this.sendSettledCheckStatus({
|
||||
state: 'error',
|
||||
message: this.isStableReleaseNotReadyFailure(sourceError)
|
||||
? "A newer release isn't available for this device yet. Check again later."
|
||||
: "Couldn't reach the update server. Try again in a few minutes.",
|
||||
...updaterCodedMessage(
|
||||
this.isStableReleaseNotReadyFailure(sourceError)
|
||||
? 'releaseNotReady'
|
||||
: 'updateServerUnreachable'
|
||||
),
|
||||
userInitiated: true
|
||||
})
|
||||
} else {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getRetainedLinuxPackageManualInstallStatus } from '../linux-package-dow
|
||||
import type { UpdateCheckOptions, UpdateStatus } from '../../shared/update-status-types'
|
||||
import type { UpdateCheckVariant } from './updater-types'
|
||||
import { UpdaterStatus } from './updater-status'
|
||||
import type { UpdaterCodedMessage } from '../../shared/updater-failure-copy'
|
||||
import {
|
||||
AUTO_UPDATE_CHECK_INTERVAL_MS,
|
||||
AUTO_UPDATE_RETRY_INTERVAL_MS,
|
||||
@@ -265,7 +266,9 @@ export abstract class UpdaterCheckState extends UpdaterStatus {
|
||||
)
|
||||
}
|
||||
|
||||
protected sendErrorStatus(message: string, userInitiated?: boolean): void {
|
||||
protected sendErrorStatus(failure: string | UpdaterCodedMessage, userInitiated?: boolean): void {
|
||||
const coded = typeof failure === 'string' ? { message: failure } : failure
|
||||
const { message } = coded
|
||||
if (
|
||||
this.currentStatus.state === 'error' &&
|
||||
this.currentStatus.message === message &&
|
||||
@@ -280,7 +283,7 @@ export abstract class UpdaterCheckState extends UpdaterStatus {
|
||||
message: 'Windows update signature check could not run'
|
||||
})
|
||||
}
|
||||
this.sendStatus({ state: 'error', message, userInitiated })
|
||||
this.sendStatus({ state: 'error', ...coded, userInitiated })
|
||||
}
|
||||
|
||||
/** Retain the distro-package manual-install card when settling a check; ordinary status would erase it. */
|
||||
@@ -289,7 +292,15 @@ export abstract class UpdaterCheckState extends UpdaterStatus {
|
||||
if (retainedStatus) {
|
||||
this.sendStatus(retainedStatus)
|
||||
} else if (status.state === 'error') {
|
||||
this.sendErrorStatus(status.message, status.userInitiated)
|
||||
const { message, messageCode, messageParams } = status
|
||||
this.sendErrorStatus(
|
||||
{
|
||||
message,
|
||||
...(messageCode === undefined ? {} : { messageCode }),
|
||||
...(messageParams === undefined ? {} : { messageParams })
|
||||
},
|
||||
status.userInitiated
|
||||
)
|
||||
} else {
|
||||
this.sendStatus(status)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import {
|
||||
updaterCodedMessage,
|
||||
type UpdaterCodedMessage,
|
||||
type UpdaterFailureCode,
|
||||
type UpdaterFailureParams
|
||||
} from '../../shared/updater-failure-copy'
|
||||
import { errorMessage } from '../../shared/error-message'
|
||||
|
||||
/** Thrown inside main only; handlers copy its code onto the status or IPC result. */
|
||||
export class UpdaterCodedError extends Error {
|
||||
readonly coded: UpdaterCodedMessage
|
||||
|
||||
constructor(code: UpdaterFailureCode, params?: UpdaterFailureParams) {
|
||||
const coded = updaterCodedMessage(code, params)
|
||||
super(coded.message)
|
||||
this.coded = coded
|
||||
}
|
||||
}
|
||||
|
||||
export function updaterErrorMessage(error: unknown): UpdaterCodedMessage {
|
||||
return error instanceof UpdaterCodedError ? error.coded : { message: errorMessage(error) }
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from '../updater-mac-install'
|
||||
import { recordUpdaterLifecycle } from '../updater-lifecycle-diagnostics'
|
||||
import { isExternallyManagedLinuxInstall } from '../linux-update-package-type'
|
||||
import { LINUX_PACKAGE_EXTERNALLY_MANAGED_MESSAGE } from '../linux-package-downloaded-status'
|
||||
import { updaterCodedMessage } from '../../shared/updater-failure-copy'
|
||||
import { QUIT_AND_INSTALL_DELAY_MS } from './updater-state'
|
||||
import { UpdaterRemoteStatus } from './updater-remote-status'
|
||||
import { prepareThisProcessShipItStaging } from './shipit-leftover-recovery'
|
||||
@@ -83,7 +83,7 @@ export abstract class UpdaterDownloadInstall extends UpdaterRemoteStatus {
|
||||
this.restoreReleaseUpdateSource()
|
||||
this.sendStatus({
|
||||
state: 'error',
|
||||
message: LINUX_PACKAGE_EXTERNALLY_MANAGED_MESSAGE,
|
||||
...updaterCodedMessage('linuxPackageExternallyManaged'),
|
||||
version,
|
||||
retryable: false
|
||||
})
|
||||
|
||||
@@ -10,7 +10,7 @@ import { getMacUpdateRunningInstances } from '../macos-update-running-instances'
|
||||
import { commitServeSupervisorPark } from './serve-supervisor-install-park'
|
||||
import { armUpdateInstallExitWatchdog } from '../update-install-exit-watchdog'
|
||||
import { getLinuxPackageType } from '../linux-update-package-type'
|
||||
import { LINUX_PACKAGE_MARKER_UNUSABLE_MESSAGE } from '../linux-package-downloaded-status'
|
||||
import { updaterCodedMessage } from '../../shared/updater-failure-copy'
|
||||
import { recordUpdaterLifecycle } from '../updater-lifecycle-diagnostics'
|
||||
import { requestServeUpdateHandoff, failServeUpdateHandoff } from '../serve-update-handoff'
|
||||
import { UpdaterMacInstallPreflight } from './updater-mac-install-preflight'
|
||||
@@ -54,7 +54,7 @@ export abstract class UpdaterInstallExecution extends UpdaterMacInstallPreflight
|
||||
this.sendToMainWindow('updater:quitAndInstallAborted')
|
||||
this.sendInstallFailureStatus({
|
||||
state: 'error',
|
||||
message: LINUX_PACKAGE_MARKER_UNUSABLE_MESSAGE,
|
||||
...updaterCodedMessage('linuxPackageMarkerUnusable'),
|
||||
...(pendingVersion ? { version: pendingVersion } : {})
|
||||
})
|
||||
return
|
||||
|
||||
@@ -13,24 +13,25 @@ import type {
|
||||
LinuxPackageInstallRecovery
|
||||
} from '../../shared/update-status-types'
|
||||
import { UpdaterInstallSupport } from './updater-install-support'
|
||||
import {
|
||||
updaterCodedMessage,
|
||||
updaterFailureText,
|
||||
type UpdaterFailureCode
|
||||
} from '../../shared/updater-failure-copy'
|
||||
|
||||
const LINUX_PACKAGE_RECOVERY_MESSAGES: Record<LinuxPackageRecoveryUnavailableReason, string> = {
|
||||
missing:
|
||||
'The downloaded package is no longer in the update cache. Download the update again, or get it from the official release page.',
|
||||
const LINUX_PACKAGE_RECOVERY_CODES: Record<
|
||||
LinuxPackageRecoveryUnavailableReason,
|
||||
UpdaterFailureCode
|
||||
> = {
|
||||
missing: 'linuxPackageMissing',
|
||||
// Also covers traversal/symlink escape from cache; do not claim only file type changed.
|
||||
'not-regular':
|
||||
'The downloaded package is no longer a valid file in the update cache. Download the update again, or get it from the official release page.',
|
||||
'hash-mismatch':
|
||||
'The downloaded package no longer matches the verified release, so Orca will not hand it to a package manager. Download the update again, or get it from the official release page.',
|
||||
'read-failed':
|
||||
'Orca could not read the downloaded package. Download the update again, or get it from the official release page.',
|
||||
'no-sudo':
|
||||
'No sudo command was found in the system directories, so Orca cannot build a safe install command. Show the package and install it with your package manager.',
|
||||
'no-package-manager':
|
||||
'No supported package manager was found in the system directories, so Orca cannot build a safe install command. Show the package and install it with your package manager.',
|
||||
'not-regular': 'linuxPackageNotRegular',
|
||||
'hash-mismatch': 'linuxPackageHashMismatch',
|
||||
'read-failed': 'linuxPackageReadFailed',
|
||||
'no-sudo': 'linuxPackageNoSudo',
|
||||
'no-package-manager': 'linuxPackageNoPackageManager',
|
||||
// Capture tracks absolute cache paths; invalid paths indicate a bug.
|
||||
'invalid-package-path':
|
||||
'The downloaded package is not at a usable path, so Orca cannot build a safe install command. Show the package and install it with your package manager.'
|
||||
'invalid-package-path': 'linuxPackageInvalidPath'
|
||||
}
|
||||
|
||||
// Clear status recovery with the artifact or renderer actions stay enabled.
|
||||
@@ -88,12 +89,12 @@ export abstract class UpdaterPackageRecovery extends UpdaterInstallSupport {
|
||||
): never {
|
||||
this.assertCurrentLinuxPackageRecovery(recovery, artifact)
|
||||
this.recordLinuxPackageRecoveryUnavailable(recovery, reason)
|
||||
const message = LINUX_PACKAGE_RECOVERY_MESSAGES[reason]
|
||||
const coded = updaterCodedMessage(LINUX_PACKAGE_RECOVERY_CODES[reason])
|
||||
if (RECOVERY_CLEARING_REASONS.includes(reason)) {
|
||||
clearTrackedLinuxPackageArtifact()
|
||||
this.sendStatus({ state: 'error', message, version: recovery.version })
|
||||
this.sendStatus({ state: 'error', ...coded, version: recovery.version })
|
||||
}
|
||||
throw new Error(message)
|
||||
throw new Error(coded.message)
|
||||
}
|
||||
|
||||
protected async getLinuxPackageInstallInstructions(): Promise<LinuxPackageInstallInstructions> {
|
||||
@@ -116,7 +117,7 @@ export abstract class UpdaterPackageRecovery extends UpdaterInstallSupport {
|
||||
return {
|
||||
ok: false,
|
||||
reason: result.reason,
|
||||
message: LINUX_PACKAGE_RECOVERY_MESSAGES[result.reason]
|
||||
message: updaterFailureText(LINUX_PACKAGE_RECOVERY_CODES[result.reason])
|
||||
}
|
||||
}
|
||||
this.failLinuxPackageRecovery(recovery, artifact, result.reason)
|
||||
|
||||
@@ -6,6 +6,8 @@ import { isTrustedUIRenderer } from '../ipc/ui'
|
||||
import type { Store } from '../persistence'
|
||||
import { logStartupMilestone } from '../startup/startup-diagnostics'
|
||||
import { applyProxyToElectronUpdaterSession } from '../updater/electron-updater-proxy-session'
|
||||
import { updaterErrorMessage } from '../updater/updater-coded-error'
|
||||
import { updaterCodedMessage } from '../../shared/updater-failure-copy'
|
||||
import {
|
||||
checkForUpdatesFromMenu,
|
||||
dismissAvailableUpdate,
|
||||
@@ -174,7 +176,7 @@ export function registerUpdaterHandlers(_store: Store): void {
|
||||
options?: { force?: boolean }
|
||||
): Promise<ReleaseBuildListResult> => {
|
||||
if (!RELEASE_CHANNELS.includes(channel)) {
|
||||
return { ok: false, channel, message: `Unknown release channel "${channel}".` }
|
||||
return { ok: false, channel, ...updaterCodedMessage('unknownReleaseChannel', { channel }) }
|
||||
}
|
||||
try {
|
||||
return {
|
||||
@@ -184,7 +186,7 @@ export function registerUpdaterHandlers(_store: Store): void {
|
||||
}
|
||||
} catch (error) {
|
||||
// Return expected network/rate-limit failures as data for the build picker.
|
||||
return { ok: false, channel, message: String((error as Error)?.message ?? error) }
|
||||
return { ok: false, channel, ...updaterErrorMessage(error) }
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@ const { toastSuccess } = vi.hoisted(() => ({ toastSuccess: vi.fn() }))
|
||||
vi.mock('sonner', () => ({ toast: { success: toastSuccess } }))
|
||||
|
||||
import { LinuxPackageInstallRecoveryCard } from './LinuxPackageInstallRecoveryCard'
|
||||
import { UPDATER_FAILURE_COPY } from '../../../shared/updater-failure-copy'
|
||||
|
||||
const RELEASE_URL = 'https://github.com/stablyai/orca/releases/tag/v1.4.200'
|
||||
const DIAGNOSTIC = 'pkexec: no polkit authentication agent found'
|
||||
@@ -516,7 +517,7 @@ describe('LinuxPackageInstallRecoveryCard without a usable command', () => {
|
||||
|
||||
expect(screen.queryByRole('button', { name: 'Copy Install Command' })).toBeNull()
|
||||
expect(button('Show Package').dataset.variant).toBe('default')
|
||||
expect(footnoteText()).toBe(NO_PACKAGE_MANAGER.message)
|
||||
expect(footnoteText()).toBe(UPDATER_FAILURE_COPY.linuxPackageNoPackageManager)
|
||||
expect(screen.getByText(/Quit Orca before finishing the update/)).toBeTruthy()
|
||||
|
||||
fireEvent.click(button('Download Manually'))
|
||||
@@ -534,7 +535,7 @@ describe('LinuxPackageInstallRecoveryCard without a usable command', () => {
|
||||
fireEvent.click(button('Copy Install Command'))
|
||||
await flushActions()
|
||||
|
||||
expect(footnoteText()).toBe('No sudo binary is available on this machine.')
|
||||
expect(footnoteText()).toBe(UPDATER_FAILURE_COPY.linuxPackageNoSudo)
|
||||
expect(button('Show Package').dataset.variant).toBe('default')
|
||||
expect(button('Download Manually')).toBeTruthy()
|
||||
})
|
||||
|
||||
@@ -6,6 +6,7 @@ import type {
|
||||
} from '../../../shared/update-status-types'
|
||||
import { UpdateErrorCardContent } from './UpdateErrorCardContent'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { linuxPackageCommandUnavailableText } from '@/lib/updater-message-copy'
|
||||
import { useMountedRef } from '@/hooks/useMountedRef'
|
||||
|
||||
function copiedNote(packageFileName: string): string {
|
||||
@@ -91,7 +92,7 @@ export function LinuxPackageInstallRecoveryCard({
|
||||
if (!instructions.ok) {
|
||||
if (isCurrentRecovery()) {
|
||||
setCommandUnavailable(true)
|
||||
setActionError(instructions.message)
|
||||
setActionError(linuxPackageCommandUnavailableText(instructions))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useAppStore } from '../store'
|
||||
import { Card } from './ui/card'
|
||||
import { Button } from './ui/button'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { updaterMessageText } from '@/lib/updater-message-copy'
|
||||
import { UpdateCardStateContent } from './maintenance/update-card/UpdateCardStateContent'
|
||||
import { buildUpdateCardErrorModel } from './maintenance/update-card/update-card-error-model'
|
||||
import {
|
||||
@@ -168,7 +169,7 @@ export function UpdateCard(): React.JSX.Element | null {
|
||||
})
|
||||
const linuxPackageRecovery =
|
||||
status.state === 'error' && status.recovery?.kind === 'linux-package-install'
|
||||
? { recovery: status.recovery, diagnostic: status.message }
|
||||
? { recovery: status.recovery, diagnostic: updaterMessageText(status) }
|
||||
: null
|
||||
const handleDismissWithAnimation = (): void => {
|
||||
if (prefersReducedMotion) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
} from '../../../../../shared/updater-windows-signature-check'
|
||||
import { getReleaseNotesUrlForVersion } from '../../../../../shared/release-channel'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { updaterMessageText } from '@/lib/updater-message-copy'
|
||||
import { isHttp2ProtocolError } from './update-card-visibility'
|
||||
|
||||
export function buildUpdateCardErrorModel({
|
||||
@@ -51,12 +52,14 @@ export function buildUpdateCardErrorModel({
|
||||
}
|
||||
: null
|
||||
}
|
||||
// Raw checks below match the host's English; display text translates known codes.
|
||||
const message = updaterMessageText(status)
|
||||
if (status.installBlock && status.retryAction === 'install' && status.retryable !== false) {
|
||||
return {
|
||||
variant: 'waiting',
|
||||
...getUpdateInstallBlockGuidance(status.installBlock),
|
||||
blockers: status.installBlock.instances,
|
||||
detail: status.message,
|
||||
detail: message,
|
||||
deferLabel: translate('updates.installBlock.later', 'Later'),
|
||||
footnote: {
|
||||
text: translate(
|
||||
@@ -73,8 +76,8 @@ export function buildUpdateCardErrorModel({
|
||||
if (status.retryAction === 'install' && status.retryable !== false) {
|
||||
return {
|
||||
title: translate('auto.components.UpdateCard.4cf109845a', 'Update Error'),
|
||||
summary: status.message,
|
||||
detail: status.message,
|
||||
summary: message,
|
||||
detail: message,
|
||||
releaseUrl: getReleaseNotesUrlForVersion(cachedVersion),
|
||||
primaryAction: {
|
||||
label: translate('auto.components.UpdateCard.2c2d3e03ca', 'Try Again'),
|
||||
@@ -96,7 +99,7 @@ export function buildUpdateCardErrorModel({
|
||||
'auto.components.UpdateCard.d29740d175',
|
||||
'The selected build could not be used.'
|
||||
),
|
||||
detail: status.message,
|
||||
detail: message,
|
||||
primaryAction: {
|
||||
label: translate('auto.components.UpdateCard.37d45c9ec1', 'Choose Another Build'),
|
||||
onClick: onChooseLocalBuild
|
||||
@@ -115,7 +118,7 @@ export function buildUpdateCardErrorModel({
|
||||
'auto.components.UpdateCard.90559b14e3',
|
||||
'This turns on a process-wide Electron networking switch after restart. Use it for corporate VPNs or proxies that reject HTTP/2 update downloads.'
|
||||
),
|
||||
detail: compatibilitySetupError ?? status.message,
|
||||
detail: compatibilitySetupError ?? message,
|
||||
releaseUrl: getReleaseNotesUrlForVersion(cachedVersion),
|
||||
primaryAction: {
|
||||
label: translate('auto.components.UpdateCard.933c6fdf5b', 'Enable & Restart'),
|
||||
@@ -133,7 +136,7 @@ export function buildUpdateCardErrorModel({
|
||||
'auto.components.UpdateCard.092f09fc14',
|
||||
"The installer's publisher doesn't match Orca, so we stopped the update. Don't install this download; check official releases for a corrected version."
|
||||
),
|
||||
detail: status.message,
|
||||
detail: message,
|
||||
releaseUrl: getReleaseNotesUrlForVersion(null),
|
||||
manualLabel: translate('auto.components.UpdateCard.c9ff9b9ec2', 'Check official releases')
|
||||
}
|
||||
@@ -145,7 +148,7 @@ export function buildUpdateCardErrorModel({
|
||||
'auto.components.UpdateCard.a05992a26b',
|
||||
"The signature check couldn't run — usually because antivirus software blocked it. Retry the download, or get the installer from our official releases."
|
||||
),
|
||||
detail: status.message,
|
||||
detail: message,
|
||||
releaseUrl: getReleaseNotesUrlForVersion(cachedVersion),
|
||||
primaryAction: {
|
||||
label: translate('auto.components.UpdateCard.48565a32bc', 'Retry Download'),
|
||||
@@ -159,14 +162,14 @@ export function buildUpdateCardErrorModel({
|
||||
: translate('auto.components.UpdateCard.updateCheckFailed', 'Update Check Failed'),
|
||||
summary:
|
||||
cachedVersion && status.retryable === false
|
||||
? status.message
|
||||
? message
|
||||
: cachedVersion
|
||||
? translate(
|
||||
'auto.components.UpdateCard.updateIncomplete',
|
||||
'Could not complete the update.'
|
||||
)
|
||||
: translate('auto.components.UpdateCard.checkFailed', 'Could not check for updates.'),
|
||||
detail: status.message,
|
||||
detail: message,
|
||||
releaseUrl: getReleaseNotesUrlForVersion(cachedVersion),
|
||||
primaryAction:
|
||||
cachedVersion && status.retryable !== false
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Button } from '../ui/button'
|
||||
import { SearchableSetting } from './SearchableSetting'
|
||||
import { SettingsSubsectionHeader } from './SettingsFormControls'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { updaterMessageText } from '@/lib/updater-message-copy'
|
||||
import { getUpdateCheckClickOptions, getUpdateCheckHint } from '@/lib/update-check-click-options'
|
||||
import { GeneralRemoteServerUpdates } from './GeneralRemoteServerUpdates'
|
||||
import { ReleaseChannelSection } from './ReleaseChannelSection'
|
||||
@@ -243,17 +244,17 @@ export function GeneralUpdateSettingsSection(): React.JSX.Element {
|
||||
(updateStatus.installBlock
|
||||
? getUpdateInstallBlockGuidance(updateStatus.installBlock).explainer
|
||||
: updateStatus.recovery?.kind === 'linux-package-install'
|
||||
? updateStatus.message
|
||||
? updaterMessageText(updateStatus)
|
||||
: updateVersionRef.current
|
||||
? translate(
|
||||
'auto.components.settings.GeneralUpdateSettingsSection.b9ad70c30d',
|
||||
'Update error. {{value0}}',
|
||||
{ value0: updateStatus.message }
|
||||
{ value0: updaterMessageText(updateStatus) }
|
||||
)
|
||||
: translate(
|
||||
'auto.components.settings.GeneralUpdateSettingsSection.bd79d412f0',
|
||||
'Update check failed. {{value0}}',
|
||||
{ value0: updateStatus.message }
|
||||
{ value0: updaterMessageText(updateStatus) }
|
||||
))}
|
||||
</p>
|
||||
</SearchableSetting>
|
||||
|
||||
@@ -8,6 +8,9 @@ import { ReleaseBuildPicker } from './ReleaseBuildPicker'
|
||||
import { SettingsSegmentedControl, SettingsSubsectionHeader } from './SettingsFormControls'
|
||||
import { Badge } from '../ui/badge'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { updaterMessageText } from '@/lib/updater-message-copy'
|
||||
import { errorMessage } from '../../../../shared/error-message'
|
||||
import type { UpdaterCodedMessage } from '../../../../shared/updater-failure-copy'
|
||||
import { getShortcutPlatform } from '@/lib/shortcut-platform'
|
||||
import {
|
||||
DEV_CHANNEL_PLATFORM_LABEL,
|
||||
@@ -57,7 +60,7 @@ export function ReleaseChannelSection(): React.JSX.Element {
|
||||
|
||||
const [appVersion, setAppVersion] = useState<string | null>(null)
|
||||
const [builds, setBuilds] = useState<ReleaseBuild[] | null>(null)
|
||||
const [loadError, setLoadError] = useState<string | null>(null)
|
||||
const [loadError, setLoadError] = useState<UpdaterCodedMessage | null>(null)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [selectedTag, setSelectedTag] = useState<string | null>(null)
|
||||
|
||||
@@ -102,14 +105,14 @@ export function ReleaseChannelSection(): React.JSX.Element {
|
||||
setSelectedTag(result.builds[0]?.tag ?? null)
|
||||
} else {
|
||||
setBuilds(null)
|
||||
setLoadError(result.message)
|
||||
setLoadError(result)
|
||||
}
|
||||
} catch (error) {
|
||||
if (isStale()) {
|
||||
return
|
||||
}
|
||||
setBuilds(null)
|
||||
setLoadError(String((error as Error)?.message ?? error))
|
||||
setLoadError({ message: errorMessage(error) })
|
||||
} finally {
|
||||
// Only the newest request may clear loading; old completions must not flash No builds.
|
||||
if (!isStale()) {
|
||||
@@ -312,7 +315,7 @@ export function ReleaseChannelSection(): React.JSX.Element {
|
||||
</p>
|
||||
|
||||
{loadError ? (
|
||||
<p className="text-xs text-destructive">{loadError}</p>
|
||||
<p className="text-xs text-destructive">{updaterMessageText(loadError)}</p>
|
||||
) : needsManualInstall && selectedBuild ? (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{translate(
|
||||
|
||||
+32
@@ -2346,6 +2346,38 @@
|
||||
"count_other": "{{count}} running terminals"
|
||||
}
|
||||
},
|
||||
"updates": {
|
||||
"failure": {
|
||||
"channelUnsupportedPlatform": "{{channel}} builds are produced only for macOS and Windows.",
|
||||
"invalidReleaseTag": "\"{{tag}}\" is not a valid release tag.",
|
||||
"linuxPackageExternallyManaged": "This copy of Orca is managed by your system package manager, so Orca cannot install updates itself. Update Orca through your distribution instead.",
|
||||
"linuxPackageHashMismatch": "The downloaded package no longer matches the verified release, so Orca will not hand it to a package manager. Download the update again, or get it from the official release page.",
|
||||
"linuxPackageInvalidPath": "The downloaded package is not at a usable path, so Orca cannot build a safe install command. Show the package and install it with your package manager.",
|
||||
"linuxPackageManualInstall": "Quit Orca before running the system package install command.",
|
||||
"linuxPackageMarkerUnusable": "Orca could not verify the installed Linux package format, so it will not install this update automatically. Download the update from the official release page and install it manually.",
|
||||
"linuxPackageMetadataUnusable": "The downloaded package metadata could not be verified. Quit Orca before downloading and installing the update from the official release page.",
|
||||
"linuxPackageMissing": "The downloaded package is no longer in the update cache. Download the update again, or get it from the official release page.",
|
||||
"linuxPackageNoPackageManager": "No supported package manager was found in the system directories, so Orca cannot build a safe install command. Show the package and install it with your package manager.",
|
||||
"linuxPackageNoSudo": "No sudo command was found in the system directories, so Orca cannot build a safe install command. Show the package and install it with your package manager.",
|
||||
"linuxPackageNotRegular": "The downloaded package is no longer a valid file in the update cache. Download the update again, or get it from the official release page.",
|
||||
"linuxPackageReadFailed": "Orca could not read the downloaded package. Download the update again, or get it from the official release page.",
|
||||
"rateLimitedInMinute": "GitHub rate limit reached. Try again in about a minute.",
|
||||
"rateLimitedInMinuteSignedOut": "GitHub rate limit reached. Try again in about a minute, or run `gh auth login` so Orca can use your account's higher limit.",
|
||||
"rateLimitedInMinutesSignedOut_one": "GitHub rate limit reached. Try again in about {{count}} minute, or run `gh auth login` so Orca can use your account's higher limit.",
|
||||
"rateLimitedInMinutesSignedOut_other": "GitHub rate limit reached. Try again in about {{count}} minutes, or run `gh auth login` so Orca can use your account's higher limit.",
|
||||
"rateLimitedInMinutes_one": "GitHub rate limit reached. Try again in about {{count}} minute.",
|
||||
"rateLimitedInMinutes_other": "GitHub rate limit reached. Try again in about {{count}} minutes.",
|
||||
"rateLimitedSoon": "GitHub rate limit reached. Try again in a few minutes.",
|
||||
"rateLimitedSoonSignedOut": "GitHub rate limit reached. Try again in a few minutes, or run `gh auth login` so Orca can use your account's higher limit.",
|
||||
"releaseListFailed": "Could not list {{channel}} builds (HTTP {{status}}).",
|
||||
"releaseListUnreadable": "Could not read the {{channel}} release list.",
|
||||
"releaseNotReady": "A newer release isn't available for this device yet. Check again later.",
|
||||
"releaseRepoNotFound": "No releases repository found at {{repo}}.",
|
||||
"unknownReleaseChannel": "Unknown release channel \"{{channel}}\".",
|
||||
"unsignedDevChannel": "{{channel}} builds are unsigned, and this signed build only installs updates signed by Orca's publisher. Download the installer from the release page and run it once — updates work normally from there, including back to Stable.",
|
||||
"updateServerUnreachable": "Couldn't reach the update server. Try again in a few minutes."
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"links": {
|
||||
"linkedCount_one": "{{count}} linked",
|
||||
|
||||
@@ -21142,7 +21142,37 @@
|
||||
"preparingAriaLabel": "Das Update wird vorbereitet. Zum Aufklappen klicken."
|
||||
},
|
||||
"wslMoveInstallHeld": "Ein Projekt wird auf seinen WSL-Host verschoben. Das Update nach Abschluss des Verschiebens installieren.",
|
||||
"wslMoveUndoInstallHeld": "Ein Projekt wird von seinem WSL-Host zurückgeholt. Das Update danach installieren."
|
||||
"wslMoveUndoInstallHeld": "Ein Projekt wird von seinem WSL-Host zurückgeholt. Das Update danach installieren.",
|
||||
"failure": {
|
||||
"releaseNotReady": "Für dieses Gerät ist noch keine neuere Version verfügbar. Später erneut prüfen.",
|
||||
"updateServerUnreachable": "Der Update-Server konnte nicht erreicht werden. In einigen Minuten erneut versuchen.",
|
||||
"channelUnsupportedPlatform": "{{channel}}-Builds werden nur für macOS und Windows erstellt.",
|
||||
"unsignedDevChannel": "{{channel}}-Builds sind nicht signiert. Dieser signierte Build installiert nur Updates, die vom Herausgeber von Orca signiert wurden. Das Installationsprogramm von der Release-Seite herunterladen und einmal ausführen – danach funktionieren Updates wie gewohnt, auch zurück zu Stable.",
|
||||
"linuxPackageMissing": "Das heruntergeladene Paket ist nicht mehr im Update-Cache vorhanden. Das Update erneut herunterladen oder von der offiziellen Release-Seite beziehen.",
|
||||
"linuxPackageNotRegular": "Das heruntergeladene Paket ist im Update-Cache keine gültige Datei mehr. Das Update erneut herunterladen oder von der offiziellen Release-Seite beziehen.",
|
||||
"linuxPackageHashMismatch": "Das heruntergeladene Paket stimmt nicht mehr mit der überprüften Version überein. Orca übergibt es daher nicht an eine Paketverwaltung. Das Update erneut herunterladen oder von der offiziellen Release-Seite beziehen.",
|
||||
"linuxPackageReadFailed": "Orca konnte das heruntergeladene Paket nicht lesen. Das Update erneut herunterladen oder von der offiziellen Release-Seite beziehen.",
|
||||
"linuxPackageNoSudo": "In den Systemverzeichnissen wurde kein sudo-Befehl gefunden. Orca kann daher keinen sicheren Installationsbefehl erstellen. Das Paket anzeigen und über die Paketverwaltung installieren.",
|
||||
"linuxPackageNoPackageManager": "In den Systemverzeichnissen wurde keine unterstützte Paketverwaltung gefunden. Orca kann daher keinen sicheren Installationsbefehl erstellen. Das Paket anzeigen und über die Paketverwaltung installieren.",
|
||||
"linuxPackageInvalidPath": "Das heruntergeladene Paket liegt nicht unter einem verwendbaren Pfad. Orca kann daher keinen sicheren Installationsbefehl erstellen. Das Paket anzeigen und über die Paketverwaltung installieren.",
|
||||
"linuxPackageMarkerUnusable": "Orca konnte das Format des installierten Linux-Pakets nicht überprüfen und installiert dieses Update daher nicht automatisch. Das Update von der offiziellen Release-Seite herunterladen und manuell installieren.",
|
||||
"linuxPackageExternallyManaged": "Diese Orca-Installation wird von der Paketverwaltung des Systems verwaltet. Orca kann Updates daher nicht selbst installieren. Orca stattdessen über die Distribution aktualisieren.",
|
||||
"linuxPackageManualInstall": "Orca beenden, bevor der Systembefehl zur Paketinstallation ausgeführt wird.",
|
||||
"linuxPackageMetadataUnusable": "Die Metadaten des heruntergeladenen Pakets konnten nicht überprüft werden. Orca beenden, bevor das Update von der offiziellen Release-Seite heruntergeladen und installiert wird.",
|
||||
"unknownReleaseChannel": "Unbekannter Veröffentlichungskanal „{{channel}}“.",
|
||||
"invalidReleaseTag": "„{{tag}}“ ist kein gültiges Release-Tag.",
|
||||
"releaseRepoNotFound": "Unter {{repo}} wurde kein Release-Repository gefunden.",
|
||||
"releaseListFailed": "{{channel}}-Builds konnten nicht aufgelistet werden (HTTP {{status}}).",
|
||||
"releaseListUnreadable": "Die Release-Liste für {{channel}} konnte nicht gelesen werden.",
|
||||
"rateLimitedSoon": "GitHub-Ratenlimit erreicht. In einigen Minuten erneut versuchen.",
|
||||
"rateLimitedSoonSignedOut": "GitHub-Ratenlimit erreicht. In einigen Minuten erneut versuchen oder `gh auth login` ausführen, damit Orca das höhere Limit deines Kontos nutzen kann.",
|
||||
"rateLimitedInMinute": "GitHub-Ratenlimit erreicht. In etwa einer Minute erneut versuchen.",
|
||||
"rateLimitedInMinuteSignedOut": "GitHub-Ratenlimit erreicht. In etwa einer Minute erneut versuchen oder `gh auth login` ausführen, damit Orca das höhere Limit deines Kontos nutzen kann.",
|
||||
"rateLimitedInMinutes_one": "GitHub-Ratenlimit erreicht. In etwa {{count}} Minute erneut versuchen.",
|
||||
"rateLimitedInMinutes_other": "GitHub-Ratenlimit erreicht. In etwa {{count}} Minuten erneut versuchen.",
|
||||
"rateLimitedInMinutesSignedOut_one": "GitHub-Ratenlimit erreicht. In etwa {{count}} Minute erneut versuchen oder `gh auth login` ausführen, damit Orca das höhere Limit deines Kontos nutzen kann.",
|
||||
"rateLimitedInMinutesSignedOut_other": "GitHub-Ratenlimit erreicht. In etwa {{count}} Minuten erneut versuchen oder `gh auth login` ausführen, damit Orca das höhere Limit deines Kontos nutzen kann."
|
||||
}
|
||||
},
|
||||
"jira": {
|
||||
"connect": {
|
||||
|
||||
@@ -21563,7 +21563,37 @@
|
||||
"preparingAriaLabel": "Preparing update. Click to expand."
|
||||
},
|
||||
"wslMoveInstallHeld": "A project is moving to its WSL host. Install the update once the move finishes.",
|
||||
"wslMoveUndoInstallHeld": "A project is coming back from its WSL host. Install the update once that finishes."
|
||||
"wslMoveUndoInstallHeld": "A project is coming back from its WSL host. Install the update once that finishes.",
|
||||
"failure": {
|
||||
"releaseNotReady": "A newer release isn't available for this device yet. Check again later.",
|
||||
"updateServerUnreachable": "Couldn't reach the update server. Try again in a few minutes.",
|
||||
"channelUnsupportedPlatform": "{{channel}} builds are produced only for macOS and Windows.",
|
||||
"unsignedDevChannel": "{{channel}} builds are unsigned, and this signed build only installs updates signed by Orca's publisher. Download the installer from the release page and run it once — updates work normally from there, including back to Stable.",
|
||||
"linuxPackageMissing": "The downloaded package is no longer in the update cache. Download the update again, or get it from the official release page.",
|
||||
"linuxPackageNotRegular": "The downloaded package is no longer a valid file in the update cache. Download the update again, or get it from the official release page.",
|
||||
"linuxPackageHashMismatch": "The downloaded package no longer matches the verified release, so Orca will not hand it to a package manager. Download the update again, or get it from the official release page.",
|
||||
"linuxPackageReadFailed": "Orca could not read the downloaded package. Download the update again, or get it from the official release page.",
|
||||
"linuxPackageNoSudo": "No sudo command was found in the system directories, so Orca cannot build a safe install command. Show the package and install it with your package manager.",
|
||||
"linuxPackageNoPackageManager": "No supported package manager was found in the system directories, so Orca cannot build a safe install command. Show the package and install it with your package manager.",
|
||||
"linuxPackageInvalidPath": "The downloaded package is not at a usable path, so Orca cannot build a safe install command. Show the package and install it with your package manager.",
|
||||
"linuxPackageMarkerUnusable": "Orca could not verify the installed Linux package format, so it will not install this update automatically. Download the update from the official release page and install it manually.",
|
||||
"linuxPackageExternallyManaged": "This copy of Orca is managed by your system package manager, so Orca cannot install updates itself. Update Orca through your distribution instead.",
|
||||
"linuxPackageManualInstall": "Quit Orca before running the system package install command.",
|
||||
"linuxPackageMetadataUnusable": "The downloaded package metadata could not be verified. Quit Orca before downloading and installing the update from the official release page.",
|
||||
"unknownReleaseChannel": "Unknown release channel \"{{channel}}\".",
|
||||
"invalidReleaseTag": "\"{{tag}}\" is not a valid release tag.",
|
||||
"releaseRepoNotFound": "No releases repository found at {{repo}}.",
|
||||
"releaseListFailed": "Could not list {{channel}} builds (HTTP {{status}}).",
|
||||
"releaseListUnreadable": "Could not read the {{channel}} release list.",
|
||||
"rateLimitedSoon": "GitHub rate limit reached. Try again in a few minutes.",
|
||||
"rateLimitedSoonSignedOut": "GitHub rate limit reached. Try again in a few minutes, or run `gh auth login` so Orca can use your account's higher limit.",
|
||||
"rateLimitedInMinute": "GitHub rate limit reached. Try again in about a minute.",
|
||||
"rateLimitedInMinuteSignedOut": "GitHub rate limit reached. Try again in about a minute, or run `gh auth login` so Orca can use your account's higher limit.",
|
||||
"rateLimitedInMinutes_one": "GitHub rate limit reached. Try again in about {{count}} minute.",
|
||||
"rateLimitedInMinutes_other": "GitHub rate limit reached. Try again in about {{count}} minutes.",
|
||||
"rateLimitedInMinutesSignedOut_one": "GitHub rate limit reached. Try again in about {{count}} minute, or run `gh auth login` so Orca can use your account's higher limit.",
|
||||
"rateLimitedInMinutesSignedOut_other": "GitHub rate limit reached. Try again in about {{count}} minutes, or run `gh auth login` so Orca can use your account's higher limit."
|
||||
}
|
||||
},
|
||||
"jira": {
|
||||
"connect": {
|
||||
|
||||
@@ -21805,7 +21805,39 @@
|
||||
"browserGuidance": "Finaliza el proceso que aparece abajo y vuelve a intentarlo: su servidor seguirá funcionando sin navegador. Si otro equipo usa este Mac como host SSH, actualiza Orca en ese equipo para que el navegador pueda pausarse automáticamente durante las actualizaciones."
|
||||
},
|
||||
"wslMoveInstallHeld": "Un proyecto se está moviendo a su host WSL. Instala la actualización cuando termine el movimiento.",
|
||||
"wslMoveUndoInstallHeld": "Un proyecto está volviendo desde su host WSL. Instala la actualización cuando termine."
|
||||
"wslMoveUndoInstallHeld": "Un proyecto está volviendo desde su host WSL. Instala la actualización cuando termine.",
|
||||
"failure": {
|
||||
"releaseNotReady": "Aún no hay una versión más reciente disponible para este dispositivo. Vuelve a comprobarlo más tarde.",
|
||||
"updateServerUnreachable": "No se pudo contactar con el servidor de actualizaciones. Vuelve a intentarlo en unos minutos.",
|
||||
"channelUnsupportedPlatform": "Las versiones de {{channel}} se generan solo para macOS y Windows.",
|
||||
"unsignedDevChannel": "Las versiones de {{channel}} no están firmadas y esta versión firmada solo instala actualizaciones firmadas por el editor de Orca. Descarga el instalador desde la página de versiones y ejecútalo una vez; después, las actualizaciones funcionarán con normalidad, incluso para volver a Stable.",
|
||||
"linuxPackageMissing": "El paquete descargado ya no está en la caché de actualizaciones. Descarga la actualización de nuevo u obtenla en la página oficial de versiones.",
|
||||
"linuxPackageNotRegular": "El paquete descargado ya no es un archivo válido en la caché de actualizaciones. Descarga la actualización de nuevo u obtenla en la página oficial de versiones.",
|
||||
"linuxPackageHashMismatch": "El paquete descargado ya no coincide con la versión verificada, por lo que Orca no lo entregará a un gestor de paquetes. Descarga la actualización de nuevo u obtenla en la página oficial de versiones.",
|
||||
"linuxPackageReadFailed": "Orca no pudo leer el paquete descargado. Descarga la actualización de nuevo u obtenla en la página oficial de versiones.",
|
||||
"linuxPackageNoSudo": "No se encontró el comando sudo en los directorios del sistema, por lo que Orca no puede generar un comando de instalación seguro. Muestra el paquete e instálalo con tu gestor de paquetes.",
|
||||
"linuxPackageNoPackageManager": "No se encontró ningún gestor de paquetes compatible en los directorios del sistema, por lo que Orca no puede generar un comando de instalación seguro. Muestra el paquete e instálalo con tu gestor de paquetes.",
|
||||
"linuxPackageInvalidPath": "El paquete descargado no está en una ruta utilizable, por lo que Orca no puede generar un comando de instalación seguro. Muestra el paquete e instálalo con tu gestor de paquetes.",
|
||||
"linuxPackageMarkerUnusable": "Orca no pudo verificar el formato del paquete de Linux instalado, por lo que no instalará esta actualización automáticamente. Descarga la actualización desde la página oficial de versiones e instálala manualmente.",
|
||||
"linuxPackageExternallyManaged": "El gestor de paquetes del sistema administra esta copia de Orca, por lo que Orca no puede instalar actualizaciones por sí mismo. Actualiza Orca a través de tu distribución.",
|
||||
"linuxPackageManualInstall": "Sal de Orca antes de ejecutar el comando de instalación de paquetes del sistema.",
|
||||
"linuxPackageMetadataUnusable": "No se pudieron verificar los metadatos del paquete descargado. Sal de Orca antes de descargar e instalar la actualización desde la página oficial de versiones.",
|
||||
"unknownReleaseChannel": "Canal de lanzamiento desconocido «{{channel}}».",
|
||||
"invalidReleaseTag": "«{{tag}}» no es una etiqueta de versión válida.",
|
||||
"releaseRepoNotFound": "No se encontró ningún repositorio de versiones en {{repo}}.",
|
||||
"releaseListFailed": "No se pudieron listar las versiones de {{channel}} (HTTP {{status}}).",
|
||||
"releaseListUnreadable": "No se pudo leer la lista de versiones de {{channel}}.",
|
||||
"rateLimitedSoon": "Se alcanzó el límite de velocidad de GitHub. Inténtalo de nuevo en unos minutos.",
|
||||
"rateLimitedSoonSignedOut": "Se alcanzó el límite de velocidad de GitHub. Inténtalo de nuevo en unos minutos o ejecuta `gh auth login` para que Orca pueda usar el límite más alto de tu cuenta.",
|
||||
"rateLimitedInMinute": "Se alcanzó el límite de velocidad de GitHub. Inténtalo de nuevo en aproximadamente un minuto.",
|
||||
"rateLimitedInMinuteSignedOut": "Se alcanzó el límite de velocidad de GitHub. Inténtalo de nuevo en aproximadamente un minuto o ejecuta `gh auth login` para que Orca pueda usar el límite más alto de tu cuenta.",
|
||||
"rateLimitedInMinutes_one": "Se alcanzó el límite de velocidad de GitHub. Inténtalo de nuevo en aproximadamente {{count}} minuto.",
|
||||
"rateLimitedInMinutes_other": "Se alcanzó el límite de velocidad de GitHub. Inténtalo de nuevo en aproximadamente {{count}} minutos.",
|
||||
"rateLimitedInMinutes_many": "Se alcanzó el límite de velocidad de GitHub. Inténtalo de nuevo en aproximadamente {{count}} minutos.",
|
||||
"rateLimitedInMinutesSignedOut_one": "Se alcanzó el límite de velocidad de GitHub. Inténtalo de nuevo en aproximadamente {{count}} minuto o ejecuta `gh auth login` para que Orca pueda usar el límite más alto de tu cuenta.",
|
||||
"rateLimitedInMinutesSignedOut_other": "Se alcanzó el límite de velocidad de GitHub. Inténtalo de nuevo en aproximadamente {{count}} minutos o ejecuta `gh auth login` para que Orca pueda usar el límite más alto de tu cuenta.",
|
||||
"rateLimitedInMinutesSignedOut_many": "Se alcanzó el límite de velocidad de GitHub. Inténtalo de nuevo en aproximadamente {{count}} minutos o ejecuta `gh auth login` para que Orca pueda usar el límite más alto de tu cuenta."
|
||||
}
|
||||
},
|
||||
"jira": {
|
||||
"savedFilters": {
|
||||
|
||||
@@ -21899,7 +21899,39 @@
|
||||
"browserGuidance": "Terminez le processus ci-dessous, puis réessayez : son serveur continue de fonctionner sans navigateur. Si un autre ordinateur utilise ce Mac comme hôte SSH, la mise à jour d’Orca sur cet ordinateur permet au navigateur de se mettre automatiquement en pause lors des mises à jour."
|
||||
},
|
||||
"wslMoveInstallHeld": "Un projet est en cours de déplacement vers son hôte WSL. Installez la mise à jour une fois le déplacement terminé.",
|
||||
"wslMoveUndoInstallHeld": "Un projet est en train de revenir de son hôte WSL. Installez la mise à jour une fois l'opération terminée."
|
||||
"wslMoveUndoInstallHeld": "Un projet est en train de revenir de son hôte WSL. Installez la mise à jour une fois l'opération terminée.",
|
||||
"failure": {
|
||||
"releaseNotReady": "Aucune version plus récente n'est encore disponible pour cet appareil. Vérifiez à nouveau plus tard.",
|
||||
"updateServerUnreachable": "Impossible de joindre le serveur de mise à jour. Réessayez dans quelques minutes.",
|
||||
"channelUnsupportedPlatform": "Les versions {{channel}} sont produites uniquement pour macOS et Windows.",
|
||||
"unsignedDevChannel": "Les versions {{channel}} ne sont pas signées, et cette version signée n'installe que les mises à jour signées par l'éditeur d'Orca. Téléchargez le programme d'installation depuis la page des versions et exécutez-le une fois. Les mises à jour fonctionneront ensuite normalement, y compris pour revenir à Stable.",
|
||||
"linuxPackageMissing": "Le package téléchargé n'est plus dans le cache des mises à jour. Téléchargez à nouveau la mise à jour ou récupérez-la sur la page officielle des versions.",
|
||||
"linuxPackageNotRegular": "Le package téléchargé n'est plus un fichier valide dans le cache des mises à jour. Téléchargez à nouveau la mise à jour ou récupérez-la sur la page officielle des versions.",
|
||||
"linuxPackageHashMismatch": "Le package téléchargé ne correspond plus à la version vérifiée. Orca ne le transmettra donc pas à un gestionnaire de packages. Téléchargez à nouveau la mise à jour ou récupérez-la sur la page officielle des versions.",
|
||||
"linuxPackageReadFailed": "Orca n'a pas pu lire le package téléchargé. Téléchargez à nouveau la mise à jour ou récupérez-la sur la page officielle des versions.",
|
||||
"linuxPackageNoSudo": "La commande sudo est introuvable dans les répertoires système. Orca ne peut donc pas générer de commande d'installation sûre. Affichez le package et installez-le avec votre gestionnaire de packages.",
|
||||
"linuxPackageNoPackageManager": "Aucun gestionnaire de packages pris en charge n'a été trouvé dans les répertoires système. Orca ne peut donc pas générer de commande d'installation sûre. Affichez le package et installez-le avec votre gestionnaire de packages.",
|
||||
"linuxPackageInvalidPath": "Le chemin du package téléchargé n'est pas utilisable. Orca ne peut donc pas générer de commande d'installation sûre. Affichez le package et installez-le avec votre gestionnaire de packages.",
|
||||
"linuxPackageMarkerUnusable": "Orca n'a pas pu vérifier le format du package Linux installé et n'installera donc pas cette mise à jour automatiquement. Téléchargez la mise à jour depuis la page officielle des versions et installez-la manuellement.",
|
||||
"linuxPackageExternallyManaged": "Cette copie d'Orca est gérée par votre gestionnaire de packages système. Orca ne peut donc pas installer les mises à jour lui-même. Mettez plutôt Orca à jour via votre distribution.",
|
||||
"linuxPackageManualInstall": "Quittez Orca avant d'exécuter la commande système d'installation de packages.",
|
||||
"linuxPackageMetadataUnusable": "Les métadonnées du package téléchargé n'ont pas pu être vérifiées. Quittez Orca avant de télécharger et d'installer la mise à jour depuis la page officielle des versions.",
|
||||
"unknownReleaseChannel": "Canal de publication inconnu « {{channel}} ».",
|
||||
"invalidReleaseTag": "« {{tag}} » n'est pas un tag de version valide.",
|
||||
"releaseRepoNotFound": "Aucun dépôt de versions trouvé à l'adresse {{repo}}.",
|
||||
"releaseListFailed": "Impossible de lister les versions {{channel}} (HTTP {{status}}).",
|
||||
"releaseListUnreadable": "Impossible de lire la liste des versions {{channel}}.",
|
||||
"rateLimitedSoon": "Limite de débit GitHub atteinte. Réessayez dans quelques minutes.",
|
||||
"rateLimitedSoonSignedOut": "Limite de débit GitHub atteinte. Réessayez dans quelques minutes ou exécutez `gh auth login` pour qu'Orca puisse utiliser la limite plus élevée de votre compte.",
|
||||
"rateLimitedInMinute": "Limite de débit GitHub atteinte. Réessayez dans environ une minute.",
|
||||
"rateLimitedInMinuteSignedOut": "Limite de débit GitHub atteinte. Réessayez dans environ une minute ou exécutez `gh auth login` pour qu'Orca puisse utiliser la limite plus élevée de votre compte.",
|
||||
"rateLimitedInMinutes_one": "Limite de débit GitHub atteinte. Réessayez dans environ {{count}} minute.",
|
||||
"rateLimitedInMinutes_other": "Limite de débit GitHub atteinte. Réessayez dans environ {{count}} minutes.",
|
||||
"rateLimitedInMinutes_many": "Limite de débit GitHub atteinte. Réessayez dans environ {{count}} minutes.",
|
||||
"rateLimitedInMinutesSignedOut_one": "Limite de débit GitHub atteinte. Réessayez dans environ {{count}} minute ou exécutez `gh auth login` pour qu'Orca puisse utiliser la limite plus élevée de votre compte.",
|
||||
"rateLimitedInMinutesSignedOut_other": "Limite de débit GitHub atteinte. Réessayez dans environ {{count}} minutes ou exécutez `gh auth login` pour qu'Orca puisse utiliser la limite plus élevée de votre compte.",
|
||||
"rateLimitedInMinutesSignedOut_many": "Limite de débit GitHub atteinte. Réessayez dans environ {{count}} minutes ou exécutez `gh auth login` pour qu'Orca puisse utiliser la limite plus élevée de votre compte."
|
||||
}
|
||||
},
|
||||
"onboarding": {
|
||||
"language": {
|
||||
|
||||
@@ -21233,7 +21233,35 @@
|
||||
"browserSummary": "バックグラウンド Orca サーバーのブラウザはまだこのアプリを使用しています。"
|
||||
},
|
||||
"wslMoveInstallHeld": "プロジェクトを WSL ホストへ移動しています。移動が完了してからアップデートをインストールしてください。",
|
||||
"wslMoveUndoInstallHeld": "プロジェクトを WSL ホストから戻しています。完了してからアップデートをインストールしてください。"
|
||||
"wslMoveUndoInstallHeld": "プロジェクトを WSL ホストから戻しています。完了してからアップデートをインストールしてください。",
|
||||
"failure": {
|
||||
"releaseNotReady": "このデバイス向けの新しいリリースはまだ利用できません。後でもう一度確認してください。",
|
||||
"updateServerUnreachable": "更新サーバーに接続できませんでした。数分後にもう一度お試しください。",
|
||||
"channelUnsupportedPlatform": "{{channel}} ビルドは macOS と Windows 向けにのみ提供されます。",
|
||||
"unsignedDevChannel": "{{channel}} ビルドは未署名で、この署名済みビルドでは Orca の発行元が署名した更新のみをインストールできます。リリースページからインストーラーをダウンロードして一度実行してください。その後は Stable に戻す場合も含め、通常どおり更新できます。",
|
||||
"linuxPackageMissing": "ダウンロードしたパッケージが更新キャッシュにありません。更新を再ダウンロードするか、公式リリースページから入手してください。",
|
||||
"linuxPackageNotRegular": "更新キャッシュ内のダウンロード済みパッケージが有効なファイルではなくなっています。更新を再ダウンロードするか、公式リリースページから入手してください。",
|
||||
"linuxPackageHashMismatch": "ダウンロードしたパッケージが検証済みリリースと一致しなくなったため、Orca はパッケージマネージャーに渡しません。更新を再ダウンロードするか、公式リリースページから入手してください。",
|
||||
"linuxPackageReadFailed": "Orca はダウンロードしたパッケージを読み取れませんでした。更新を再ダウンロードするか、公式リリースページから入手してください。",
|
||||
"linuxPackageNoSudo": "システムディレクトリに sudo コマンドが見つからないため、Orca は安全なインストールコマンドを生成できません。パッケージを表示し、パッケージマネージャーでインストールしてください。",
|
||||
"linuxPackageNoPackageManager": "システムディレクトリに対応するパッケージマネージャーが見つからないため、Orca は安全なインストールコマンドを生成できません。パッケージを表示し、パッケージマネージャーでインストールしてください。",
|
||||
"linuxPackageInvalidPath": "ダウンロードしたパッケージのパスを使用できないため、Orca は安全なインストールコマンドを生成できません。パッケージを表示し、パッケージマネージャーでインストールしてください。",
|
||||
"linuxPackageMarkerUnusable": "Orca はインストール済み Linux パッケージの形式を確認できなかったため、この更新を自動インストールしません。公式リリースページから更新をダウンロードし、手動でインストールしてください。",
|
||||
"linuxPackageExternallyManaged": "この Orca はシステムのパッケージマネージャーで管理されているため、Orca 自体では更新をインストールできません。ディストリビューションの仕組みで Orca を更新してください。",
|
||||
"linuxPackageManualInstall": "システムのパッケージインストールコマンドを実行する前に Orca を終了してください。",
|
||||
"linuxPackageMetadataUnusable": "ダウンロードしたパッケージのメタデータを検証できませんでした。Orca を終了してから、公式リリースページから更新をダウンロードしてインストールしてください。",
|
||||
"unknownReleaseChannel": "不明なリリースチャンネル「{{channel}}」。",
|
||||
"invalidReleaseTag": "「{{tag}}」は有効なリリースタグではありません。",
|
||||
"releaseRepoNotFound": "{{repo}} にリリース用リポジトリが見つかりません。",
|
||||
"releaseListFailed": "{{channel}} ビルドの一覧を取得できませんでした(HTTP {{status}})。",
|
||||
"releaseListUnreadable": "{{channel}} のリリース一覧を読み取れませんでした。",
|
||||
"rateLimitedSoon": "GitHub のレート制限に達しました。数分後にもう一度お試しください。",
|
||||
"rateLimitedSoonSignedOut": "GitHub のレート制限に達しました。数分後にもう一度試すか、`gh auth login` を実行して Orca がアカウントのより高い上限を利用できるようにしてください。",
|
||||
"rateLimitedInMinute": "GitHub のレート制限に達しました。約 1 分後にもう一度お試しください。",
|
||||
"rateLimitedInMinuteSignedOut": "GitHub のレート制限に達しました。約 1 分後にもう一度試すか、`gh auth login` を実行して Orca がアカウントのより高い上限を利用できるようにしてください。",
|
||||
"rateLimitedInMinutes_other": "GitHub のレート制限に達しました。約 {{count}} 分後にもう一度お試しください。",
|
||||
"rateLimitedInMinutesSignedOut_other": "GitHub のレート制限に達しました。約 {{count}} 分後にもう一度試すか、`gh auth login` を実行して Orca がアカウントのより高い上限を利用できるようにしてください。"
|
||||
}
|
||||
},
|
||||
"onboarding": {
|
||||
"language": {
|
||||
|
||||
@@ -21233,7 +21233,35 @@
|
||||
"browserGuidance": "아래 프로세스를 종료한 후 다시 시도하세요. 서버는 브라우저 없이 계속 실행됩니다. 다른 컴퓨터가 이 Mac을 SSH 호스트로 사용하는 경우 해당 컴퓨터의 Orca를 업데이트하면 업데이트 시 브라우저가 자동으로 일시 중지됩니다."
|
||||
},
|
||||
"wslMoveInstallHeld": "프로젝트를 WSL 호스트로 옮기는 중입니다. 이동이 끝난 후 업데이트를 설치하세요.",
|
||||
"wslMoveUndoInstallHeld": "프로젝트를 WSL 호스트에서 다시 가져오는 중입니다. 완료된 후 업데이트를 설치하세요."
|
||||
"wslMoveUndoInstallHeld": "프로젝트를 WSL 호스트에서 다시 가져오는 중입니다. 완료된 후 업데이트를 설치하세요.",
|
||||
"failure": {
|
||||
"releaseNotReady": "이 기기에서는 아직 새 릴리스를 사용할 수 없습니다. 나중에 다시 확인하세요.",
|
||||
"updateServerUnreachable": "업데이트 서버에 연결할 수 없습니다. 몇 분 후 다시 시도하세요.",
|
||||
"channelUnsupportedPlatform": "{{channel}} 빌드는 macOS 및 Windows용으로만 제공됩니다.",
|
||||
"unsignedDevChannel": "{{channel}} 빌드는 서명되지 않았으며, 현재 서명된 빌드는 Orca 게시자가 서명한 업데이트만 설치합니다. 릴리스 페이지에서 설치 프로그램을 다운로드하여 한 번 실행하세요. 이후에는 Stable로 돌아가는 경우를 포함해 업데이트가 정상적으로 작동합니다.",
|
||||
"linuxPackageMissing": "다운로드한 패키지가 업데이트 캐시에 더 이상 없습니다. 업데이트를 다시 다운로드하거나 공식 릴리스 페이지에서 받으세요.",
|
||||
"linuxPackageNotRegular": "다운로드한 패키지가 업데이트 캐시에서 더 이상 유효한 파일이 아닙니다. 업데이트를 다시 다운로드하거나 공식 릴리스 페이지에서 받으세요.",
|
||||
"linuxPackageHashMismatch": "다운로드한 패키지가 검증된 릴리스와 더 이상 일치하지 않아 Orca가 패키지 관리자에 전달하지 않습니다. 업데이트를 다시 다운로드하거나 공식 릴리스 페이지에서 받으세요.",
|
||||
"linuxPackageReadFailed": "Orca가 다운로드한 패키지를 읽지 못했습니다. 업데이트를 다시 다운로드하거나 공식 릴리스 페이지에서 받으세요.",
|
||||
"linuxPackageNoSudo": "시스템 디렉터리에서 sudo 명령을 찾지 못해 Orca가 안전한 설치 명령을 생성할 수 없습니다. 패키지를 표시하고 패키지 관리자로 설치하세요.",
|
||||
"linuxPackageNoPackageManager": "시스템 디렉터리에서 지원되는 패키지 관리자를 찾지 못해 Orca가 안전한 설치 명령을 생성할 수 없습니다. 패키지를 표시하고 패키지 관리자로 설치하세요.",
|
||||
"linuxPackageInvalidPath": "다운로드한 패키지가 사용 가능한 경로에 있지 않아 Orca가 안전한 설치 명령을 생성할 수 없습니다. 패키지를 표시하고 패키지 관리자로 설치하세요.",
|
||||
"linuxPackageMarkerUnusable": "Orca가 설치된 Linux 패키지 형식을 확인하지 못해 이 업데이트를 자동으로 설치하지 않습니다. 공식 릴리스 페이지에서 업데이트를 다운로드하고 수동으로 설치하세요.",
|
||||
"linuxPackageExternallyManaged": "이 Orca는 시스템 패키지 관리자가 관리하므로 Orca가 직접 업데이트를 설치할 수 없습니다. 배포판을 통해 Orca를 업데이트하세요.",
|
||||
"linuxPackageManualInstall": "시스템 패키지 설치 명령을 실행하기 전에 Orca를 종료하세요.",
|
||||
"linuxPackageMetadataUnusable": "다운로드한 패키지의 메타데이터를 검증할 수 없습니다. Orca를 종료한 후 공식 릴리스 페이지에서 업데이트를 다운로드하고 설치하세요.",
|
||||
"unknownReleaseChannel": "알 수 없는 출시 채널 \"{{channel}}\"입니다.",
|
||||
"invalidReleaseTag": "\"{{tag}}\"은(는) 유효한 릴리스 태그가 아닙니다.",
|
||||
"releaseRepoNotFound": "{{repo}}에서 릴리스 저장소를 찾을 수 없습니다.",
|
||||
"releaseListFailed": "{{channel}} 빌드 목록을 가져올 수 없습니다(HTTP {{status}}).",
|
||||
"releaseListUnreadable": "{{channel}} 릴리스 목록을 읽을 수 없습니다.",
|
||||
"rateLimitedSoon": "GitHub 속도 제한에 도달했습니다. 몇 분 후 다시 시도하세요.",
|
||||
"rateLimitedSoonSignedOut": "GitHub 속도 제한에 도달했습니다. 몇 분 후 다시 시도하거나 `gh auth login`을 실행하여 Orca가 계정의 더 높은 한도를 사용할 수 있도록 하세요.",
|
||||
"rateLimitedInMinute": "GitHub 속도 제한에 도달했습니다. 약 1분 후 다시 시도하세요.",
|
||||
"rateLimitedInMinuteSignedOut": "GitHub 속도 제한에 도달했습니다. 약 1분 후 다시 시도하거나 `gh auth login`을 실행하여 Orca가 계정의 더 높은 한도를 사용할 수 있도록 하세요.",
|
||||
"rateLimitedInMinutes_other": "GitHub 속도 제한에 도달했습니다. 약 {{count}}분 후 다시 시도하세요.",
|
||||
"rateLimitedInMinutesSignedOut_other": "GitHub 속도 제한에 도달했습니다. 약 {{count}}분 후 다시 시도하거나 `gh auth login`을 실행하여 Orca가 계정의 더 높은 한도를 사용할 수 있도록 하세요."
|
||||
}
|
||||
},
|
||||
"onboarding": {
|
||||
"language": {
|
||||
|
||||
@@ -21559,7 +21559,39 @@
|
||||
"preparingAriaLabel": "Preparando atualização. Clique para expandir."
|
||||
},
|
||||
"wslMoveInstallHeld": "Um projeto está sendo movido para o host WSL dele. Instale a atualização quando a movimentação terminar.",
|
||||
"wslMoveUndoInstallHeld": "Um projeto está voltando do host WSL dele. Instale a atualização quando isso terminar."
|
||||
"wslMoveUndoInstallHeld": "Um projeto está voltando do host WSL dele. Instale a atualização quando isso terminar.",
|
||||
"failure": {
|
||||
"releaseNotReady": "Uma versão mais recente ainda não está disponível para este dispositivo. Verifique novamente mais tarde.",
|
||||
"updateServerUnreachable": "Não foi possível acessar o servidor de atualização. Tente novamente em alguns minutos.",
|
||||
"channelUnsupportedPlatform": "As builds {{channel}} são produzidas apenas para macOS e Windows.",
|
||||
"unsignedDevChannel": "As builds {{channel}} não são assinadas, e esta build assinada só instala atualizações assinadas pelo publicador do Orca. Baixe o instalador na página de releases e execute-o uma vez — depois disso, as atualizações funcionam normalmente, inclusive para voltar ao Stable.",
|
||||
"linuxPackageMissing": "O pacote baixado não está mais no cache de atualizações. Baixe a atualização novamente ou obtenha-a na página oficial de releases.",
|
||||
"linuxPackageNotRegular": "O pacote baixado não é mais um arquivo válido no cache de atualizações. Baixe a atualização novamente ou obtenha-a na página oficial de releases.",
|
||||
"linuxPackageHashMismatch": "O pacote baixado não corresponde mais ao release verificado, por isso o Orca não o encaminhará a um gerenciador de pacotes. Baixe a atualização novamente ou obtenha-a na página oficial de releases.",
|
||||
"linuxPackageReadFailed": "O Orca não conseguiu ler o pacote baixado. Baixe a atualização novamente ou obtenha-a na página oficial de releases.",
|
||||
"linuxPackageNoSudo": "O comando sudo não foi encontrado nos diretórios do sistema, por isso o Orca não pode gerar um comando de instalação seguro. Exiba o pacote e instale-o com seu gerenciador de pacotes.",
|
||||
"linuxPackageNoPackageManager": "Nenhum gerenciador de pacotes compatível foi encontrado nos diretórios do sistema, por isso o Orca não pode gerar um comando de instalação seguro. Exiba o pacote e instale-o com seu gerenciador de pacotes.",
|
||||
"linuxPackageInvalidPath": "O pacote baixado não está em um caminho utilizável, por isso o Orca não pode gerar um comando de instalação seguro. Exiba o pacote e instale-o com seu gerenciador de pacotes.",
|
||||
"linuxPackageMarkerUnusable": "O Orca não conseguiu verificar o formato do pacote Linux instalado, por isso não instalará esta atualização automaticamente. Baixe a atualização na página oficial de releases e instale-a manualmente.",
|
||||
"linuxPackageExternallyManaged": "Esta cópia do Orca é gerenciada pelo gerenciador de pacotes do sistema, por isso o Orca não pode instalar atualizações por conta própria. Atualize o Orca pela sua distribuição.",
|
||||
"linuxPackageManualInstall": "Encerre o Orca antes de executar o comando de instalação de pacotes do sistema.",
|
||||
"linuxPackageMetadataUnusable": "Não foi possível verificar os metadados do pacote baixado. Encerre o Orca antes de baixar e instalar a atualização pela página oficial de releases.",
|
||||
"unknownReleaseChannel": "Canal de versão desconhecido \"{{channel}}\".",
|
||||
"invalidReleaseTag": "\"{{tag}}\" não é uma tag de release válida.",
|
||||
"releaseRepoNotFound": "Nenhum repositório de releases encontrado em {{repo}}.",
|
||||
"releaseListFailed": "Não foi possível listar as builds {{channel}} (HTTP {{status}}).",
|
||||
"releaseListUnreadable": "Não foi possível ler a lista de releases de {{channel}}.",
|
||||
"rateLimitedSoon": "Limite de taxa do GitHub atingido. Tente novamente em alguns minutos.",
|
||||
"rateLimitedSoonSignedOut": "Limite de taxa do GitHub atingido. Tente novamente em alguns minutos ou execute `gh auth login` para que o Orca possa usar o limite maior da sua conta.",
|
||||
"rateLimitedInMinute": "Limite de taxa do GitHub atingido. Tente novamente em cerca de um minuto.",
|
||||
"rateLimitedInMinuteSignedOut": "Limite de taxa do GitHub atingido. Tente novamente em cerca de um minuto ou execute `gh auth login` para que o Orca possa usar o limite maior da sua conta.",
|
||||
"rateLimitedInMinutes_one": "Limite de taxa do GitHub atingido. Tente novamente em cerca de {{count}} minuto.",
|
||||
"rateLimitedInMinutes_other": "Limite de taxa do GitHub atingido. Tente novamente em cerca de {{count}} minutos.",
|
||||
"rateLimitedInMinutes_many": "Limite de taxa do GitHub atingido. Tente novamente em cerca de {{count}} minutos.",
|
||||
"rateLimitedInMinutesSignedOut_one": "Limite de taxa do GitHub atingido. Tente novamente em cerca de {{count}} minuto ou execute `gh auth login` para que o Orca possa usar o limite maior da sua conta.",
|
||||
"rateLimitedInMinutesSignedOut_other": "Limite de taxa do GitHub atingido. Tente novamente em cerca de {{count}} minutos ou execute `gh auth login` para que o Orca possa usar o limite maior da sua conta.",
|
||||
"rateLimitedInMinutesSignedOut_many": "Limite de taxa do GitHub atingido. Tente novamente em cerca de {{count}} minutos ou execute `gh auth login` para que o Orca possa usar o limite maior da sua conta."
|
||||
}
|
||||
},
|
||||
"jira": {
|
||||
"connect": {
|
||||
|
||||
@@ -21795,7 +21795,41 @@
|
||||
"preparingAriaLabel": "Подготовка обновления. Нажмите, чтобы развернуть."
|
||||
},
|
||||
"wslMoveInstallHeld": "Проект переносится на свой хост WSL. Установите обновление, когда перенос завершится.",
|
||||
"wslMoveUndoInstallHeld": "Проект возвращается со своего хоста WSL. Установите обновление, когда это завершится."
|
||||
"wslMoveUndoInstallHeld": "Проект возвращается со своего хоста WSL. Установите обновление, когда это завершится.",
|
||||
"failure": {
|
||||
"releaseNotReady": "Более новый выпуск пока недоступен для этого устройства. Проверьте позже.",
|
||||
"updateServerUnreachable": "Не удалось связаться с сервером обновлений. Повторите попытку через несколько минут.",
|
||||
"channelUnsupportedPlatform": "Сборки {{channel}} выпускаются только для macOS и Windows.",
|
||||
"unsignedDevChannel": "Сборки {{channel}} не подписаны, а эта подписанная сборка устанавливает только обновления с подписью издателя Orca. Скачайте установщик со страницы выпусков и запустите его один раз — после этого обновления будут работать как обычно, включая возврат на Stable.",
|
||||
"linuxPackageMissing": "Загруженного пакета больше нет в кэше обновлений. Загрузите обновление ещё раз или получите его на официальной странице выпусков.",
|
||||
"linuxPackageNotRegular": "Загруженный пакет больше не является допустимым файлом в кэше обновлений. Загрузите обновление ещё раз или получите его на официальной странице выпусков.",
|
||||
"linuxPackageHashMismatch": "Загруженный пакет больше не соответствует проверенному выпуску, поэтому Orca не передаст его менеджеру пакетов. Загрузите обновление ещё раз или получите его на официальной странице выпусков.",
|
||||
"linuxPackageReadFailed": "Orca не удалось прочитать загруженный пакет. Загрузите обновление ещё раз или получите его на официальной странице выпусков.",
|
||||
"linuxPackageNoSudo": "Команда sudo не найдена в системных каталогах, поэтому Orca не может сформировать безопасную команду установки. Покажите пакет и установите его через менеджер пакетов.",
|
||||
"linuxPackageNoPackageManager": "В системных каталогах не найден поддерживаемый менеджер пакетов, поэтому Orca не может сформировать безопасную команду установки. Покажите пакет и установите его через менеджер пакетов.",
|
||||
"linuxPackageInvalidPath": "Путь к загруженному пакету непригоден для использования, поэтому Orca не может сформировать безопасную команду установки. Покажите пакет и установите его через менеджер пакетов.",
|
||||
"linuxPackageMarkerUnusable": "Orca не удалось проверить формат установленного пакета Linux, поэтому это обновление не будет установлено автоматически. Загрузите обновление с официальной страницы выпусков и установите его вручную.",
|
||||
"linuxPackageExternallyManaged": "Эта копия Orca управляется системным менеджером пакетов, поэтому Orca не может устанавливать обновления самостоятельно. Обновите Orca средствами вашего дистрибутива.",
|
||||
"linuxPackageManualInstall": "Завершите работу Orca перед выполнением системной команды установки пакета.",
|
||||
"linuxPackageMetadataUnusable": "Не удалось проверить метаданные загруженного пакета. Завершите работу Orca перед загрузкой и установкой обновления с официальной страницы выпусков.",
|
||||
"unknownReleaseChannel": "Неизвестный канал выпусков «{{channel}}».",
|
||||
"invalidReleaseTag": "«{{tag}}» не является допустимым тегом выпуска.",
|
||||
"releaseRepoNotFound": "Репозиторий выпусков по адресу {{repo}} не найден.",
|
||||
"releaseListFailed": "Не удалось получить список сборок {{channel}} (HTTP {{status}}).",
|
||||
"releaseListUnreadable": "Не удалось прочитать список выпусков {{channel}}.",
|
||||
"rateLimitedSoon": "Достигнут лимит запросов GitHub. Повторите попытку через несколько минут.",
|
||||
"rateLimitedSoonSignedOut": "Достигнут лимит запросов GitHub. Повторите попытку через несколько минут или выполните `gh auth login`, чтобы Orca могла использовать более высокий лимит вашей учётной записи.",
|
||||
"rateLimitedInMinute": "Достигнут лимит запросов GitHub. Повторите попытку примерно через минуту.",
|
||||
"rateLimitedInMinuteSignedOut": "Достигнут лимит запросов GitHub. Повторите попытку примерно через минуту или выполните `gh auth login`, чтобы Orca могла использовать более высокий лимит вашей учётной записи.",
|
||||
"rateLimitedInMinutes_one": "Достигнут лимит запросов GitHub. Повторите попытку примерно через {{count}} минуту.",
|
||||
"rateLimitedInMinutes_other": "Достигнут лимит запросов GitHub. Повторите попытку примерно через {{count}} минуты.",
|
||||
"rateLimitedInMinutesSignedOut_one": "Достигнут лимит запросов GitHub. Повторите попытку примерно через {{count}} минуту или выполните `gh auth login`, чтобы Orca могла использовать более высокий лимит вашей учётной записи.",
|
||||
"rateLimitedInMinutesSignedOut_other": "Достигнут лимит запросов GitHub. Повторите попытку примерно через {{count}} минуты или выполните `gh auth login`, чтобы Orca могла использовать более высокий лимит вашей учётной записи.",
|
||||
"rateLimitedInMinutes_few": "Достигнут лимит запросов GitHub. Повторите попытку примерно через {{count}} минуты.",
|
||||
"rateLimitedInMinutes_many": "Достигнут лимит запросов GitHub. Повторите попытку примерно через {{count}} минут.",
|
||||
"rateLimitedInMinutesSignedOut_few": "Достигнут лимит запросов GitHub. Повторите попытку примерно через {{count}} минуты или выполните `gh auth login`, чтобы Orca могла использовать более высокий лимит вашей учётной записи.",
|
||||
"rateLimitedInMinutesSignedOut_many": "Достигнут лимит запросов GitHub. Повторите попытку примерно через {{count}} минут или выполните `gh auth login`, чтобы Orca могла использовать более высокий лимит вашей учётной записи."
|
||||
}
|
||||
},
|
||||
"jira": {
|
||||
"connect": {
|
||||
|
||||
@@ -21123,7 +21123,37 @@
|
||||
"preparingAriaLabel": "Güncelleme hazırlanıyor. Genişletmek için tıklayın."
|
||||
},
|
||||
"wslMoveInstallHeld": "Bir proje WSL ana makinesine taşınıyor. Taşıma bittiğinde güncellemeyi yükleyin.",
|
||||
"wslMoveUndoInstallHeld": "Bir proje WSL ana makinesinden geri getiriliyor. Bu bittiğinde güncellemeyi yükleyin."
|
||||
"wslMoveUndoInstallHeld": "Bir proje WSL ana makinesinden geri getiriliyor. Bu bittiğinde güncellemeyi yükleyin.",
|
||||
"failure": {
|
||||
"releaseNotReady": "Bu cihaz için daha yeni bir sürüm henüz kullanıma sunulmadı. Daha sonra tekrar kontrol edin.",
|
||||
"updateServerUnreachable": "Güncelleme sunucusuna ulaşılamadı. Birkaç dakika sonra tekrar deneyin.",
|
||||
"channelUnsupportedPlatform": "{{channel}} sürümleri yalnızca macOS ve Windows için üretilir.",
|
||||
"unsignedDevChannel": "{{channel}} sürümleri imzasızdır ve bu imzalı sürüm yalnızca Orca'nın yayımcısının imzaladığı güncellemeleri yükler. Yükleyiciyi sürüm sayfasından indirip bir kez çalıştırın; bundan sonra Kararlı kanalına dönüş dahil güncellemeler normal şekilde çalışır.",
|
||||
"linuxPackageMissing": "İndirilen paket artık güncelleme önbelleğinde değil. Güncellemeyi yeniden indirin veya resmi sürüm sayfasından edinin.",
|
||||
"linuxPackageNotRegular": "İndirilen paket artık güncelleme önbelleğinde geçerli bir dosya değil. Güncellemeyi yeniden indirin veya resmi sürüm sayfasından edinin.",
|
||||
"linuxPackageHashMismatch": "İndirilen paket artık doğrulanmış sürümle eşleşmediğinden Orca paketi bir paket yöneticisine aktarmayacak. Güncellemeyi yeniden indirin veya resmi sürüm sayfasından edinin.",
|
||||
"linuxPackageReadFailed": "Orca indirilen paketi okuyamadı. Güncellemeyi yeniden indirin veya resmi sürüm sayfasından edinin.",
|
||||
"linuxPackageNoSudo": "Sistem dizinlerinde sudo komutu bulunamadığından Orca güvenli bir kurulum komutu oluşturamıyor. Paketi gösterin ve paket yöneticinizle yükleyin.",
|
||||
"linuxPackageNoPackageManager": "Sistem dizinlerinde desteklenen bir paket yöneticisi bulunamadığından Orca güvenli bir kurulum komutu oluşturamıyor. Paketi gösterin ve paket yöneticinizle yükleyin.",
|
||||
"linuxPackageInvalidPath": "İndirilen paket kullanılabilir bir yolda olmadığından Orca güvenli bir kurulum komutu oluşturamıyor. Paketi gösterin ve paket yöneticinizle yükleyin.",
|
||||
"linuxPackageMarkerUnusable": "Orca kurulu Linux paketinin biçimini doğrulayamadığından bu güncellemeyi otomatik yüklemeyecek. Güncellemeyi resmi sürüm sayfasından indirin ve elle yükleyin.",
|
||||
"linuxPackageExternallyManaged": "Bu Orca kopyası sistem paket yöneticiniz tarafından yönetildiğinden Orca güncellemeleri kendisi yükleyemez. Orca'yı dağıtımınız üzerinden güncelleyin.",
|
||||
"linuxPackageManualInstall": "Sistemin paket yükleme komutunu çalıştırmadan önce Orca'dan çıkın.",
|
||||
"linuxPackageMetadataUnusable": "İndirilen paketin meta verileri doğrulanamadı. Güncellemeyi resmi sürüm sayfasından indirip yüklemeden önce Orca'dan çıkın.",
|
||||
"unknownReleaseChannel": "Bilinmeyen yayın kanalı \"{{channel}}\".",
|
||||
"invalidReleaseTag": "\"{{tag}}\" geçerli bir sürüm etiketi değil.",
|
||||
"releaseRepoNotFound": "{{repo}} adresinde sürümlerin yayımlandığı bir repo bulunamadı.",
|
||||
"releaseListFailed": "{{channel}} sürümleri listelenemedi (HTTP {{status}}).",
|
||||
"releaseListUnreadable": "{{channel}} sürüm listesi okunamadı.",
|
||||
"rateLimitedSoon": "GitHub istek sınırına ulaşıldı. Birkaç dakika sonra tekrar deneyin.",
|
||||
"rateLimitedSoonSignedOut": "GitHub istek sınırına ulaşıldı. Birkaç dakika sonra tekrar deneyin veya Orca'nın hesabınızdaki daha yüksek sınırı kullanabilmesi için `gh auth login` komutunu çalıştırın.",
|
||||
"rateLimitedInMinute": "GitHub istek sınırına ulaşıldı. Yaklaşık bir dakika sonra tekrar deneyin.",
|
||||
"rateLimitedInMinuteSignedOut": "GitHub istek sınırına ulaşıldı. Yaklaşık bir dakika sonra tekrar deneyin veya Orca'nın hesabınızdaki daha yüksek sınırı kullanabilmesi için `gh auth login` komutunu çalıştırın.",
|
||||
"rateLimitedInMinutes_one": "GitHub istek sınırına ulaşıldı. Yaklaşık {{count}} dakika sonra tekrar deneyin.",
|
||||
"rateLimitedInMinutes_other": "GitHub istek sınırına ulaşıldı. Yaklaşık {{count}} dakika sonra tekrar deneyin.",
|
||||
"rateLimitedInMinutesSignedOut_one": "GitHub istek sınırına ulaşıldı. Yaklaşık {{count}} dakika sonra tekrar deneyin veya Orca'nın hesabınızdaki daha yüksek sınırı kullanabilmesi için `gh auth login` komutunu çalıştırın.",
|
||||
"rateLimitedInMinutesSignedOut_other": "GitHub istek sınırına ulaşıldı. Yaklaşık {{count}} dakika sonra tekrar deneyin veya Orca'nın hesabınızdaki daha yüksek sınırı kullanabilmesi için `gh auth login` komutunu çalıştırın."
|
||||
}
|
||||
},
|
||||
"jira": {
|
||||
"connect": {
|
||||
|
||||
@@ -20845,7 +20845,35 @@
|
||||
"preparingAriaLabel": "正在準備更新。點選展開。"
|
||||
},
|
||||
"wslMoveInstallHeld": "專案正在移到其 WSL 主機。移動完成後再安裝更新。",
|
||||
"wslMoveUndoInstallHeld": "專案正在從其 WSL 主機移回。完成後再安裝更新。"
|
||||
"wslMoveUndoInstallHeld": "專案正在從其 WSL 主機移回。完成後再安裝更新。",
|
||||
"failure": {
|
||||
"releaseNotReady": "此裝置尚無可用的較新版本。請稍後再檢查。",
|
||||
"updateServerUnreachable": "無法連線至更新伺服器。請稍候幾分鐘再試。",
|
||||
"channelUnsupportedPlatform": "{{channel}} 建置版本僅針對 macOS 和 Windows 提供。",
|
||||
"unsignedDevChannel": "{{channel}} 建置版本未經簽署,而目前已簽署的建置版本只會安裝由 Orca 發行者簽署的更新。請從發行版本頁面下載安裝程式並執行一次,之後更新即可正常運作,包括切回穩定版。",
|
||||
"linuxPackageMissing": "下載的套件已不在更新快取中。請重新下載更新,或從官方發行版本頁面取得。",
|
||||
"linuxPackageNotRegular": "更新快取中下載的套件已不再是有效檔案。請重新下載更新,或從官方發行版本頁面取得。",
|
||||
"linuxPackageHashMismatch": "下載的套件已不再符合驗證過的發行版本,因此 Orca 不會將其交給套件管理員。請重新下載更新,或從官方發行版本頁面取得。",
|
||||
"linuxPackageReadFailed": "Orca 無法讀取下載的套件。請重新下載更新,或從官方發行版本頁面取得。",
|
||||
"linuxPackageNoSudo": "系統目錄中找不到 sudo 指令,因此 Orca 無法產生安全的安裝指令。請顯示套件,並使用套件管理員安裝。",
|
||||
"linuxPackageNoPackageManager": "系統目錄中找不到支援的套件管理員,因此 Orca 無法產生安全的安裝指令。請顯示套件,並使用套件管理員安裝。",
|
||||
"linuxPackageInvalidPath": "下載的套件不在可用的路徑中,因此 Orca 無法產生安全的安裝指令。請顯示套件,並使用套件管理員安裝。",
|
||||
"linuxPackageMarkerUnusable": "Orca 無法驗證已安裝的 Linux 套件格式,因此不會自動安裝此更新。請從官方發行版本頁面下載更新並手動安裝。",
|
||||
"linuxPackageExternallyManaged": "此 Orca 由系統套件管理員管理,因此 Orca 無法自行安裝更新。請透過您使用的發行版更新 Orca。",
|
||||
"linuxPackageManualInstall": "執行系統套件安裝指令前,請先結束 Orca。",
|
||||
"linuxPackageMetadataUnusable": "無法驗證下載套件的後設資料。請先結束 Orca,再從官方發行版本頁面下載並安裝更新。",
|
||||
"unknownReleaseChannel": "未知的發布頻道「{{channel}}」。",
|
||||
"invalidReleaseTag": "「{{tag}}」不是有效的發行版本標籤。",
|
||||
"releaseRepoNotFound": "在 {{repo}} 找不到發行版本存放庫。",
|
||||
"releaseListFailed": "無法列出 {{channel}} 建置版本(HTTP {{status}})。",
|
||||
"releaseListUnreadable": "無法讀取 {{channel}} 的發行版本清單。",
|
||||
"rateLimitedSoon": "已達 GitHub 速率限制。請稍候幾分鐘再試。",
|
||||
"rateLimitedSoonSignedOut": "已達 GitHub 速率限制。請稍候幾分鐘再試,或執行 `gh auth login`,讓 Orca 使用您帳戶的較高額度。",
|
||||
"rateLimitedInMinute": "已達 GitHub 速率限制。請約一分鐘後再試。",
|
||||
"rateLimitedInMinuteSignedOut": "已達 GitHub 速率限制。請約一分鐘後再試,或執行 `gh auth login`,讓 Orca 使用您帳戶的較高額度。",
|
||||
"rateLimitedInMinutes_other": "已達 GitHub 速率限制。請約 {{count}} 分鐘後再試。",
|
||||
"rateLimitedInMinutesSignedOut_other": "已達 GitHub 速率限制。請約 {{count}} 分鐘後再試,或執行 `gh auth login`,讓 Orca 使用您帳戶的較高額度。"
|
||||
}
|
||||
},
|
||||
"jira": {
|
||||
"connect": {
|
||||
|
||||
@@ -21234,7 +21234,35 @@
|
||||
"browserSummary": "后台 Orca 服务器的浏览器仍在使用此应用程序。"
|
||||
},
|
||||
"wslMoveInstallHeld": "项目正在移到其 WSL 主机。移动完成后再安装更新。",
|
||||
"wslMoveUndoInstallHeld": "项目正在从其 WSL 主机移回。完成后再安装更新。"
|
||||
"wslMoveUndoInstallHeld": "项目正在从其 WSL 主机移回。完成后再安装更新。",
|
||||
"failure": {
|
||||
"releaseNotReady": "此设备暂时还无法获取更新的版本。请稍后再检查。",
|
||||
"updateServerUnreachable": "无法连接更新服务器。请几分钟后重试。",
|
||||
"channelUnsupportedPlatform": "{{channel}} 构建仅针对 macOS 和 Windows 提供。",
|
||||
"unsignedDevChannel": "{{channel}} 构建未签名,而当前已签名的构建仅安装由 Orca 发布者签名的更新。请从版本发布页面下载安装程序并运行一次,之后更新即可正常进行,包括切回稳定版。",
|
||||
"linuxPackageMissing": "下载的安装包已不在更新缓存中。请重新下载更新,或从官方版本发布页面获取。",
|
||||
"linuxPackageNotRegular": "更新缓存中下载的安装包已不再是有效文件。请重新下载更新,或从官方版本发布页面获取。",
|
||||
"linuxPackageHashMismatch": "下载的安装包与已验证的版本不再匹配,因此 Orca 不会将其交给包管理器。请重新下载更新,或从官方版本发布页面获取。",
|
||||
"linuxPackageReadFailed": "Orca 无法读取下载的安装包。请重新下载更新,或从官方版本发布页面获取。",
|
||||
"linuxPackageNoSudo": "系统目录中未找到 sudo 命令,因此 Orca 无法生成安全的安装命令。请显示安装包并使用包管理器安装。",
|
||||
"linuxPackageNoPackageManager": "系统目录中未找到受支持的包管理器,因此 Orca 无法生成安全的安装命令。请显示安装包并使用包管理器安装。",
|
||||
"linuxPackageInvalidPath": "下载的安装包不在可用路径中,因此 Orca 无法生成安全的安装命令。请显示安装包并使用包管理器安装。",
|
||||
"linuxPackageMarkerUnusable": "Orca 无法验证已安装的 Linux 软件包格式,因此不会自动安装此更新。请从官方版本发布页面下载更新并手动安装。",
|
||||
"linuxPackageExternallyManaged": "此 Orca 由系统包管理器管理,因此 Orca 无法自行安装更新。请通过所用的发行版更新 Orca。",
|
||||
"linuxPackageManualInstall": "运行系统软件包安装命令前,请先退出 Orca。",
|
||||
"linuxPackageMetadataUnusable": "无法验证下载的安装包元数据。请先退出 Orca,再从官方版本发布页面下载并安装更新。",
|
||||
"unknownReleaseChannel": "未知的发布渠道“{{channel}}”。",
|
||||
"invalidReleaseTag": "“{{tag}}”不是有效的发布标签。",
|
||||
"releaseRepoNotFound": "在 {{repo}} 未找到发布版本的仓库。",
|
||||
"releaseListFailed": "无法列出 {{channel}} 构建(HTTP {{status}})。",
|
||||
"releaseListUnreadable": "无法读取 {{channel}} 的版本发布列表。",
|
||||
"rateLimitedSoon": "已达到 GitHub 速率限制。请几分钟后重试。",
|
||||
"rateLimitedSoonSignedOut": "已达到 GitHub 速率限制。请几分钟后重试,或运行 `gh auth login`,以便 Orca 使用你账户的更高限额。",
|
||||
"rateLimitedInMinute": "已达到 GitHub 速率限制。请约一分钟后重试。",
|
||||
"rateLimitedInMinuteSignedOut": "已达到 GitHub 速率限制。请约一分钟后重试,或运行 `gh auth login`,以便 Orca 使用你账户的更高限额。",
|
||||
"rateLimitedInMinutes_other": "已达到 GitHub 速率限制。请约 {{count}} 分钟后重试。",
|
||||
"rateLimitedInMinutesSignedOut_other": "已达到 GitHub 速率限制。请约 {{count}} 分钟后重试,或运行 `gh auth login`,以便 Orca 使用你账户的更高限额。"
|
||||
}
|
||||
},
|
||||
"onboarding": {
|
||||
"language": {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { i18n } from '@/i18n/i18n'
|
||||
import es from '@/i18n/locales/es.json'
|
||||
import { updaterCodedMessage } from '../../../shared/updater-failure-copy'
|
||||
import { updaterMessageText } from './updater-message-copy'
|
||||
|
||||
const originalLanguage = i18n.language
|
||||
|
||||
afterEach(async () => {
|
||||
await i18n.changeLanguage(originalLanguage)
|
||||
})
|
||||
|
||||
describe('updater message copy', () => {
|
||||
it('translates coded updater messages and keeps channel names verbatim', async () => {
|
||||
i18n.addResourceBundle('es', 'translation', es)
|
||||
await i18n.changeLanguage('es')
|
||||
expect(updaterMessageText(updaterCodedMessage('updateServerUnreachable'))).toBe(
|
||||
es.updates.failure.updateServerUnreachable
|
||||
)
|
||||
expect(
|
||||
updaterMessageText(updaterCodedMessage('unsignedDevChannel', { channel: 'Hourly' }))
|
||||
).toBe(es.updates.failure.unsignedDevChannel.replace('{{channel}}', 'Hourly'))
|
||||
})
|
||||
|
||||
it('keeps the English message for older hosts, unknown codes and missing params', async () => {
|
||||
i18n.addResourceBundle('es', 'translation', es)
|
||||
await i18n.changeLanguage('es')
|
||||
expect(updaterMessageText({ message: 'Older host text' })).toBe('Older host text')
|
||||
expect(updaterMessageText({ message: 'Newer host text', messageCode: 'futureCode' })).toBe(
|
||||
'Newer host text'
|
||||
)
|
||||
expect(
|
||||
updaterMessageText({
|
||||
message: 'Hourly builds are unsigned…',
|
||||
messageCode: 'unsignedDevChannel'
|
||||
})
|
||||
).toBe('Hourly builds are unsigned…')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,158 @@
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import type { LinuxPackageCommandUnavailableReason } from '../../../shared/update-status-types'
|
||||
import {
|
||||
UPDATER_FAILURE_COPY as EN,
|
||||
type UpdaterFailureCode
|
||||
} from '../../../shared/updater-failure-copy'
|
||||
|
||||
type Param = (name: string) => string | null
|
||||
type CountParam = (name: string) => number | null
|
||||
|
||||
// null = required params missing; caller shows the host's English message.
|
||||
const COPY: Record<UpdaterFailureCode, (param: Param, count: CountParam) => string | null> = {
|
||||
releaseNotReady: () => translate('updates.failure.releaseNotReady', EN.releaseNotReady),
|
||||
updateServerUnreachable: () =>
|
||||
translate('updates.failure.updateServerUnreachable', EN.updateServerUnreachable),
|
||||
channelUnsupportedPlatform: (param) => {
|
||||
const channel = param('channel')
|
||||
return channel === null
|
||||
? null
|
||||
: translate('updates.failure.channelUnsupportedPlatform', EN.channelUnsupportedPlatform, {
|
||||
channel
|
||||
})
|
||||
},
|
||||
unsignedDevChannel: (param) => {
|
||||
const channel = param('channel')
|
||||
return channel === null
|
||||
? null
|
||||
: translate('updates.failure.unsignedDevChannel', EN.unsignedDevChannel, { channel })
|
||||
},
|
||||
linuxPackageMissing: () =>
|
||||
translate('updates.failure.linuxPackageMissing', EN.linuxPackageMissing),
|
||||
linuxPackageNotRegular: () =>
|
||||
translate('updates.failure.linuxPackageNotRegular', EN.linuxPackageNotRegular),
|
||||
linuxPackageHashMismatch: () =>
|
||||
translate('updates.failure.linuxPackageHashMismatch', EN.linuxPackageHashMismatch),
|
||||
linuxPackageReadFailed: () =>
|
||||
translate('updates.failure.linuxPackageReadFailed', EN.linuxPackageReadFailed),
|
||||
linuxPackageNoSudo: () => translate('updates.failure.linuxPackageNoSudo', EN.linuxPackageNoSudo),
|
||||
linuxPackageNoPackageManager: () =>
|
||||
translate('updates.failure.linuxPackageNoPackageManager', EN.linuxPackageNoPackageManager),
|
||||
linuxPackageInvalidPath: () =>
|
||||
translate('updates.failure.linuxPackageInvalidPath', EN.linuxPackageInvalidPath),
|
||||
linuxPackageMarkerUnusable: () =>
|
||||
translate('updates.failure.linuxPackageMarkerUnusable', EN.linuxPackageMarkerUnusable),
|
||||
linuxPackageExternallyManaged: () =>
|
||||
translate('updates.failure.linuxPackageExternallyManaged', EN.linuxPackageExternallyManaged),
|
||||
linuxPackageManualInstall: () =>
|
||||
translate('updates.failure.linuxPackageManualInstall', EN.linuxPackageManualInstall),
|
||||
linuxPackageMetadataUnusable: () =>
|
||||
translate('updates.failure.linuxPackageMetadataUnusable', EN.linuxPackageMetadataUnusable),
|
||||
unknownReleaseChannel: (param) => {
|
||||
const channel = param('channel')
|
||||
return channel === null
|
||||
? null
|
||||
: translate('updates.failure.unknownReleaseChannel', EN.unknownReleaseChannel, { channel })
|
||||
},
|
||||
invalidReleaseTag: (param) => {
|
||||
const tag = param('tag')
|
||||
return tag === null
|
||||
? null
|
||||
: translate('updates.failure.invalidReleaseTag', EN.invalidReleaseTag, { tag })
|
||||
},
|
||||
releaseRepoNotFound: (param) => {
|
||||
const repo = param('repo')
|
||||
return repo === null
|
||||
? null
|
||||
: translate('updates.failure.releaseRepoNotFound', EN.releaseRepoNotFound, { repo })
|
||||
},
|
||||
releaseListFailed: (param, count) => {
|
||||
const channel = param('channel')
|
||||
const status = count('status')
|
||||
return channel === null || status === null
|
||||
? null
|
||||
: translate('updates.failure.releaseListFailed', EN.releaseListFailed, { channel, status })
|
||||
},
|
||||
releaseListUnreadable: (param) => {
|
||||
const channel = param('channel')
|
||||
return channel === null
|
||||
? null
|
||||
: translate('updates.failure.releaseListUnreadable', EN.releaseListUnreadable, { channel })
|
||||
},
|
||||
rateLimitedSoon: () => translate('updates.failure.rateLimitedSoon', EN.rateLimitedSoon),
|
||||
rateLimitedSoonSignedOut: () =>
|
||||
translate('updates.failure.rateLimitedSoonSignedOut', EN.rateLimitedSoonSignedOut),
|
||||
rateLimitedInMinute: () =>
|
||||
translate('updates.failure.rateLimitedInMinute', EN.rateLimitedInMinute),
|
||||
rateLimitedInMinuteSignedOut: () =>
|
||||
translate('updates.failure.rateLimitedInMinuteSignedOut', EN.rateLimitedInMinuteSignedOut),
|
||||
rateLimitedInMinutes: (_param, count) => {
|
||||
const minutes = count('count')
|
||||
return minutes === null
|
||||
? null
|
||||
: translate('updates.failure.rateLimitedInMinutes', EN.rateLimitedInMinutes, {
|
||||
count: minutes,
|
||||
defaultValue_one: 'GitHub rate limit reached. Try again in about {{count}} minute.'
|
||||
})
|
||||
},
|
||||
rateLimitedInMinutesSignedOut: (_param, count) => {
|
||||
const minutes = count('count')
|
||||
return minutes === null
|
||||
? null
|
||||
: translate(
|
||||
'updates.failure.rateLimitedInMinutesSignedOut',
|
||||
EN.rateLimitedInMinutesSignedOut,
|
||||
{
|
||||
count: minutes,
|
||||
defaultValue_one:
|
||||
"GitHub rate limit reached. Try again in about {{count}} minute, or run `gh auth login` so Orca can use your account's higher limit."
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const COMMAND_UNAVAILABLE_CODES: Record<LinuxPackageCommandUnavailableReason, UpdaterFailureCode> =
|
||||
{
|
||||
'no-sudo': 'linuxPackageNoSudo',
|
||||
'no-package-manager': 'linuxPackageNoPackageManager'
|
||||
}
|
||||
|
||||
function isUpdaterFailureCode(code: unknown): code is UpdaterFailureCode {
|
||||
return typeof code === 'string' && Object.hasOwn(COPY, code)
|
||||
}
|
||||
|
||||
function codedText(code: unknown, params: unknown): string | null {
|
||||
if (!isUpdaterFailureCode(code)) {
|
||||
return null
|
||||
}
|
||||
const values: Record<string, unknown> =
|
||||
typeof params === 'object' && params !== null ? Object.fromEntries(Object.entries(params)) : {}
|
||||
return COPY[code](
|
||||
(name) => (typeof values[name] === 'string' ? values[name] : null),
|
||||
(name) => (typeof values[name] === 'number' ? values[name] : null)
|
||||
)
|
||||
}
|
||||
|
||||
/** Updater message text: known codes translate; unknown codes and older hosts keep the English message. */
|
||||
export function updaterMessageText(source: {
|
||||
message: string
|
||||
messageCode?: unknown
|
||||
messageParams?: unknown
|
||||
}): string {
|
||||
return codedText(source.messageCode, source.messageParams) ?? source.message
|
||||
}
|
||||
|
||||
/** The install-instructions result already names its reason; unknown reasons keep main's English. */
|
||||
export function linuxPackageCommandUnavailableText(instructions: {
|
||||
reason: LinuxPackageCommandUnavailableReason
|
||||
message: string
|
||||
}): string {
|
||||
return (
|
||||
codedText(
|
||||
Object.hasOwn(COMMAND_UNAVAILABLE_CODES, instructions.reason)
|
||||
? COMMAND_UNAVAILABLE_CODES[instructions.reason]
|
||||
: undefined,
|
||||
undefined
|
||||
) ?? instructions.message
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { RemoteServerUpdaterSnapshot } from '../../../shared/remote-server-update'
|
||||
import { updaterMessageText } from '@/lib/updater-message-copy'
|
||||
|
||||
type PollingTransport = {
|
||||
getUpdaterStatus: (environmentId: string) => Promise<RemoteServerUpdaterSnapshot>
|
||||
@@ -23,7 +24,7 @@ export async function pollRemoteServerUpdater(
|
||||
while (now() < deadline) {
|
||||
const snapshot = await transport.getUpdaterStatus(environmentId)
|
||||
if (snapshot.status.state === 'error') {
|
||||
throw new Error(snapshot.status.message)
|
||||
throw new Error(updaterMessageText(snapshot.status))
|
||||
}
|
||||
onSnapshot(snapshot)
|
||||
if (accept(snapshot)) {
|
||||
|
||||
@@ -90,6 +90,9 @@ export type UpdateStatus = (
|
||||
| {
|
||||
state: 'error'
|
||||
message: string
|
||||
/** Translation code for `message`; older hosts omit it and newer ones may send unknown codes. */
|
||||
messageCode?: string
|
||||
messageParams?: Record<string, string | number>
|
||||
/** Known download/install target; absent for check-time failures and older hosts. */
|
||||
version?: string
|
||||
/** Omitted by older hosts and for failures whose retryability is unknown. */
|
||||
@@ -106,4 +109,10 @@ export type UpdateStatus = (
|
||||
|
||||
export type ReleaseBuildListResult =
|
||||
| { ok: true; channel: ReleaseChannel; builds: ReleaseBuild[] }
|
||||
| { ok: false; channel: ReleaseChannel; message: string }
|
||||
| {
|
||||
ok: false
|
||||
channel: ReleaseChannel
|
||||
message: string
|
||||
messageCode?: string
|
||||
messageParams?: Record<string, string | number>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// One English table for updater failures: main builds the English `message`, the renderer translates by code.
|
||||
export const UPDATER_FAILURE_COPY = {
|
||||
releaseNotReady: "A newer release isn't available for this device yet. Check again later.",
|
||||
updateServerUnreachable: "Couldn't reach the update server. Try again in a few minutes.",
|
||||
channelUnsupportedPlatform: '{{channel}} builds are produced only for macOS and Windows.',
|
||||
unsignedDevChannel:
|
||||
"{{channel}} builds are unsigned, and this signed build only installs updates signed by Orca's publisher. Download the installer from the release page and run it once — updates work normally from there, including back to Stable.",
|
||||
linuxPackageMissing:
|
||||
'The downloaded package is no longer in the update cache. Download the update again, or get it from the official release page.',
|
||||
linuxPackageNotRegular:
|
||||
'The downloaded package is no longer a valid file in the update cache. Download the update again, or get it from the official release page.',
|
||||
linuxPackageHashMismatch:
|
||||
'The downloaded package no longer matches the verified release, so Orca will not hand it to a package manager. Download the update again, or get it from the official release page.',
|
||||
linuxPackageReadFailed:
|
||||
'Orca could not read the downloaded package. Download the update again, or get it from the official release page.',
|
||||
linuxPackageNoSudo:
|
||||
'No sudo command was found in the system directories, so Orca cannot build a safe install command. Show the package and install it with your package manager.',
|
||||
linuxPackageNoPackageManager:
|
||||
'No supported package manager was found in the system directories, so Orca cannot build a safe install command. Show the package and install it with your package manager.',
|
||||
linuxPackageInvalidPath:
|
||||
'The downloaded package is not at a usable path, so Orca cannot build a safe install command. Show the package and install it with your package manager.',
|
||||
linuxPackageMarkerUnusable:
|
||||
'Orca could not verify the installed Linux package format, so it will not install this update automatically. Download the update from the official release page and install it manually.',
|
||||
linuxPackageExternallyManaged:
|
||||
'This copy of Orca is managed by your system package manager, so Orca cannot install updates itself. Update Orca through your distribution instead.',
|
||||
linuxPackageManualInstall: 'Quit Orca before running the system package install command.',
|
||||
linuxPackageMetadataUnusable:
|
||||
'The downloaded package metadata could not be verified. Quit Orca before downloading and installing the update from the official release page.',
|
||||
unknownReleaseChannel: 'Unknown release channel "{{channel}}".',
|
||||
invalidReleaseTag: '"{{tag}}" is not a valid release tag.',
|
||||
releaseRepoNotFound: 'No releases repository found at {{repo}}.',
|
||||
releaseListFailed: 'Could not list {{channel}} builds (HTTP {{status}}).',
|
||||
releaseListUnreadable: 'Could not read the {{channel}} release list.',
|
||||
rateLimitedSoon: 'GitHub rate limit reached. Try again in a few minutes.',
|
||||
rateLimitedSoonSignedOut:
|
||||
"GitHub rate limit reached. Try again in a few minutes, or run `gh auth login` so Orca can use your account's higher limit.",
|
||||
rateLimitedInMinute: 'GitHub rate limit reached. Try again in about a minute.',
|
||||
rateLimitedInMinuteSignedOut:
|
||||
"GitHub rate limit reached. Try again in about a minute, or run `gh auth login` so Orca can use your account's higher limit.",
|
||||
// Only for two or more minutes; one minute uses rateLimitedInMinute.
|
||||
rateLimitedInMinutes: 'GitHub rate limit reached. Try again in about {{count}} minutes.',
|
||||
rateLimitedInMinutesSignedOut:
|
||||
"GitHub rate limit reached. Try again in about {{count}} minutes, or run `gh auth login` so Orca can use your account's higher limit."
|
||||
} as const
|
||||
|
||||
export type UpdaterFailureCode = keyof typeof UPDATER_FAILURE_COPY
|
||||
|
||||
export type UpdaterFailureParams = Record<string, string | number>
|
||||
|
||||
/** Wire shape: `message` stays English for older readers; code and params let the renderer translate it. */
|
||||
export type UpdaterCodedMessage = {
|
||||
message: string
|
||||
messageCode?: string
|
||||
messageParams?: UpdaterFailureParams
|
||||
}
|
||||
|
||||
// One pass, so a value containing "{{status}}" stays verbatim.
|
||||
export function updaterFailureText(
|
||||
code: UpdaterFailureCode,
|
||||
params: UpdaterFailureParams = {}
|
||||
): string {
|
||||
return UPDATER_FAILURE_COPY[code].replace(/\{\{(\w+)\}\}/g, (slot, name: string) =>
|
||||
Object.hasOwn(params, name) ? String(params[name]) : slot
|
||||
)
|
||||
}
|
||||
|
||||
export function updaterCodedMessage(
|
||||
code: UpdaterFailureCode,
|
||||
params?: UpdaterFailureParams
|
||||
): UpdaterCodedMessage {
|
||||
return {
|
||||
message: updaterFailureText(code, params),
|
||||
messageCode: code,
|
||||
...(params ? { messageParams: params } : {})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user