✨ feat: add suggestions, translation & key endpoints to api-client - #74
Merged
elisiondan merged 7 commits intoAug 12, 2026
Merged
Conversation
The `@see` link on `ai.translate` referenced `/docs/api/ai-translation`, which returns 404. The published page is `/docs/api/ai-translation-api`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Features
- Add `api.suggestions` with `tm()`, `mt()` and `ai()` over
`/projects/{p}/keys/{id}/suggestions/{tm|mt|ai}`
- `ai()` is a POST because it spends AI credits, mirroring the API
- Accept a locale code or numeric language id for `to` and `from`
- Mirror the response envelope exactly so `enabled`, `errors` and empty
`items` stay distinguishable from one another
- Type engine names as open unions: the active engine set is deployment
configuration and can grow without a client release
## Tests
- Cover both language forms, soft errors, the disabled case and the
preservation of caller-supplied `config.params`
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Features - Add `keys.submitTranslation` for one key in one target language - Add `keys.setTags` and `keys.setPriority` over the batch routes, both returning `BooleanResult` so a caller can see the API answered — note it reports the request was processed, not that anything changed - URL-escape the locale so script-qualified codes such as `zh#Hans` survive instead of being truncated at the fragment marker - Accept the `@`-prefixed plural form the read API returns and strip it, so a value taken straight from `files.listKeys()` round-trips safely - Derive `PluralClass` and `KeyPriority` from single runtime lists ## Bug fixes - Guard `getIds` against a non-array, and reject a nullish language instead of coercing it to the literal string `"null"` ## Tests - Cover locale escaping, plural prefix stripping, mixed key arrays and the rejection paths Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Features
- Add `plural()` so a plural value is spelled once and rendered per endpoint:
`@`-prefixed on import, plain on `keys.submitTranslation`
- Resolve markers before the import payload is chunked, since the chunker
recurses into every plain object and would otherwise split one
- Leave unmarked objects untouched: without the prefix `{ one, other }` is a
legitimate nested key group, so the prefix cannot be inferred
## Tests
- Assert the marker never reaches the wire, that unmarked objects stay nested,
and that every CLDR class is recognised by iterating the shared list
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…rals Both defects predate the suggestion work and affect every import, not only plural payloads. They were found while testing the plural import path. ## Bug fixes - Fold chunk leaves with `reduce` instead of spreading them into `merge`: one argument per leaf overflowed the call stack, so any import approaching `CHUNK_LIMIT` threw `RangeError` before a request was ever sent - Treat a plural object as a single leaf, the way `@meta:` keys already were. Emitting one leaf per class let a key's forms land in different chunks and upload as two files with partial forms The second defect was unreachable in practice because the first crashed first, so fixing either alone would have been incomplete. ## Tests - Cover atomicity, a payload at the chunk limit, and a plural sitting on a real chunk boundary Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Documentation - Add reference entries for the suggestion, translation, tag and priority methods, each with a runnable example - Add a Plural keys section covering the per-endpoint spelling, `plural()`, and why an unmarked object declares nested keys instead - State what the types check and what they cannot: excess-property checking only applies to object literals - Backfill the missing `keys.deprecate` entry and correct the AI translation link that pointed at a 404 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Generated by `pnpm run main-ts:build`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
honzabubenik
approved these changes
Aug 12, 2026
elisiondan
deleted the
LOC-4645_add_suggestions_translation__key_endpoints_to_apiclient
branch
August 12, 2026 09:57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes LOC-4645.
Wraps four public API capabilities that were missing from
@localazy/api-client, plus two pre-existingJsonUtilsfixes found while testing.What's new
api.suggestions—tm(),mt(),ai()over/keys/{id}/suggestions/{tm|mt|ai}.ai()is a POST because it spends credits, mirroring the API. The response envelope is mirrored exactly soenabled,errorsand emptyitemsstay distinguishable — collapsing them is how a caller ends up reporting "MT is off" when the key simply had no source text.api.keys—submitTranslation,setTags,setPriority. The bulk methods use the batch routes and returnBooleanResult.plural()— a plural value spelled once and rendered per endpoint:@-prefixed on import, plain on submit. On import the prefix is the only thing separating a plural from a nested key group, and both readings are well-typed, so the compiler cannot catch the mistake.Pre-existing fixes (please review separately)
Neither is caused by this feature; both are in
16ae6cdand affect every import:mergeChunkValuesoverflowed the call stack — it spread one argument per leaf, so any import approachingCHUNK_LIMIT(99,000) threwRangeErrorbefore a request was sent. Large imports were simply broken.The second was unreachable because the first crashed first, so fixing either alone would have been incomplete.
Also fixed: the
ai.translate@seelink pointed at a 404, andkeys.deprecatewas missing from the reference doc.Verification
Full gate green — 78 tests. Exercised live against production (project Figma app):
suggestions.tm/mtkeys.submitTranslationkeys.setTags/setPriorityimport.jsonwithplural()Notes
Known… | (string & Record<never, never>)): the active engine set is deployment configuration, so a closed union would go wrong the moment an engine ships server-side.