Skip to content

ADFA-5404 | Recover from missing offline language packs - #95

Open
jatezzz wants to merge 1 commit into
fix/ADFA-5403-resolve-llm-from-shared-servicesfrom
fix/ADFA-5404-language-pack-error-handling
Open

ADFA-5404 | Recover from missing offline language packs#95
jatezzz wants to merge 1 commit into
fix/ADFA-5403-resolve-llm-from-shared-servicesfrom
fix/ADFA-5404-language-pack-error-handling

Conversation

@jatezzz

@jatezzz jatezzz commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Description

Replaces the generic "unknown error 12" with clear, actionable UI messages that display the specific missing Locale. Implements an automatic single online retry when an offline language pack is missing, ensuring the user's dictation session stays alive without being prematurely aborted.

Details

  • Handled ERROR_LANGUAGE_UNAVAILABLE and ERROR_LANGUAGE_NOT_SUPPORTED in SpeechToTextPlugin.kt.
  • Parameterized preferOffline and set EXTRA_LANGUAGE to support a single online retry attempt.
  • Added detailed UI toasts in strings.xml to inform the user of the exact failing language and the fallback network attempt.
  • Updated index.html documentation to reflect the new language pack recovery behavior.

Prompt EN: Function that reverses a string
Prompt ES: Función que reversa un string

document_4976756881377724759.mp4

Ticket

ADFA-5404
Parent: ADFA-5402

Observation

The plugin now queries checkRecognitionSupport on API 33+ devices to find regional fallback packs or trigger downloads, defaulting to a direct network retry on older SDKs.

…A-5404)

Recognize in the host's configured locale, and on error 12/13 retry once with an installed pack for the same language or online while fetching the missing pack, instead of failing the capture with "unknown error 12".

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@hal-eisen-adfa

Copy link
Copy Markdown
Contributor

I posted on Slack about strings.xml review

@hal-eisen-adfa hal-eisen-adfa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review (Claude Code, high). The branch compiles clean and every new API symbol resolves in libs/plugin-api.jar; the new %1$s/%2$s positions match their str() call sites. Two findings below.

Not device-verified — build only.

// One capture at a time: a second recognizer would race the first for the microphone
// and for the transcript. A capture stuck past the LLM timeout is treated as over.
val elapsed = System.currentTimeMillis() - captureStartedAt
if (recordingState != RecordingState.IDLE && elapsed < STALE_CAPTURE_MS) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

F28 (High) — the busy guard expires 42 s before the generation it guards.

STALE_CAPTURE_MS is 90_000 (line 1008), but GENERATION_TIMEOUT_SECONDS is MAX_GENERATION_TOKENS / SLOWEST_TOKENS_PER_SECOND + PROMPT_EVAL_SECONDS = 512 / 5 + 30 = 132 s (lines 989-990). The comment above this line — "A capture stuck past the LLM timeout is treated as over" — is false for every generation that runs between 90 s and 132 s, which is exactly the slow on-device case the timeout was sized for.

On a slow backend:

Derive the constant so the two cannot drift. Both operands are already const, so this stays a compile-time constant:

private const val STALE_CAPTURE_MS =
    GENERATION_TIMEOUT_SECONDS * MILLIS_PER_SECOND + STALE_CAPTURE_HEADROOM_MS

val locale = activeLocale
val requested = languageLabel()

val installed = usableTag(support.installedOnDeviceLanguages, locale)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

F30 (Medium) — the installed-pack branch can retry the exact locale that just failed.

usableTag tries an exact match first (line 633), so when the recognizer lists the requested tag in installedOnDeviceLanguages, installed is the tag that just returned ERROR_LANGUAGE_UNAVAILABLE / ERROR_LANGUAGE_NOT_SUPPORTED. restartRecognition(preferOffline = true, locale = fallback) then re-issues the identical request.

A device that reports en-US installed but still errors 13 — a partly-installed or corrupt pack, the common cause of this bug class — fails the retry the same way. languageFallbackSpent is now true, so the capture ends and the online retry that would have worked is never reached.

The toast contradicts itself too: "No offline pack for English (United States) (en-US), so English (United States) is being used instead".

Exclude the failing tag from the installed match. An exact hit then falls through to retryOnline(), while a different-region pack (en-GB for a failed en-US) still short-circuits — that second case is the one this branch is actually for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants