Skip to content

feat(i18n): add locale query param to opportunity and suggestion GET endpoints | LLMO-5430#2649

Open
Sihalnic-Alin wants to merge 3 commits into
adobe:mainfrom
Sihalnic-Alin:LLMO-5430-unlocalized-strings-in-opportunities
Open

feat(i18n): add locale query param to opportunity and suggestion GET endpoints | LLMO-5430#2649
Sihalnic-Alin wants to merge 3 commits into
adobe:mainfrom
Sihalnic-Alin:LLMO-5430-unlocalized-strings-in-opportunities

Conversation

@Sihalnic-Alin

Copy link
Copy Markdown

Changes Made

Adds a ?locale= query parameter to all opportunity and suggestion GET endpoints so that AI-generated content can be returned in the user's selected language once audit workers begin storing translations alongside English content.

  • OpportunityDto: toJSON(oppty, locale) reads data.i18n[locale] and promotes matching title/description values to the top-level response fields; strips data.i18n from the response so the shape stays stable
  • SuggestionDto: toJSON(suggestion, view, opportunity, locale) merges data.i18n[locale] on top of the data object (covering title, rationale, description, expectedOutcome, actionItems, persona); strips data.i18n from the response
  • OpportunitiesController: all three GET handlers (getAllForSite, getByStatus, getByID) extract locale from query params and pass it to the DTO
  • SuggestionsController: all five GET handlers (getAllForOpportunity, getAllForOpportunityPaged, getByStatus, getByStatusPaged, getByID) extract locale and pass it to the DTO
  • OpenAPI (parameters.yaml, site-opportunities.yaml): new locale query parameter defined with regex ^[a-z]{2}_[a-z]{2}$ and referenced on all GET opportunity/suggestion endpoints
  • Tests: new test/dto/opportunity.test.js (8 cases) + 5 locale projection cases added to test/dto/suggestion.test.js

Storage contract for audit workers (Phase 2 — separate PR per worker):
Translations should be stored in data.i18n[locale] when creating/patching opportunities and suggestions:

// opportunity.data
{ "i18n": { "fr_fr": { "title": "...", "description": "..." } } }

// suggestion.data
{ "i18n": { "fr_fr": { "title": "...", "rationale": "...", "actionItems": [...] } } }

Missing or absent translations fall back to the original English values — fully non-breaking.

Companion FE PR: adobe/project-elmo-ui#2124 (localizes static UI strings; Phase 3 — passing ?locale= from the UI — is a follow-up once audit workers populate translations)

Related Issues

Relates to LLMO-5430

Testing the PR changes

  1. Run unit tests: npm test — all 497 tests pass
  2. Start the service locally (cp .env.example .env && npm start)
  3. PATCH an opportunity to inject a test translation:
    curl -X PATCH \
      -H "x-api-key: api_key_for_user_requests" \
      -H "Content-Type: application/json" \
      -d '{"data": {"i18n": {"fr_fr": {"title": "Titre de test en français"}}}}' \
      "http://localhost:3002/sites/<siteId>/opportunities/<opportunityId>"
  4. Fetch with ?locale=fr_fr and verify title returns the French value:
    curl -H "x-api-key: api_key_for_user_requests" \
      "http://localhost:3002/sites/<siteId>/opportunities/<opportunityId>?locale=fr_fr"
  5. Fetch without ?locale and verify the original English title is returned (non-breaking)
  6. Verify data.i18n is absent from both responses

Screenshots/Videos

No screenshots available.

Additional Notes

N/A

…endpoints | LLMO-5430

Add ?locale=<code> support to all opportunity and suggestion read endpoints so
that AI-generated content (title/description on opportunities; title/rationale/
description/actionItems/persona inside suggestion data) can be returned in the
user's selected language once audit workers begin storing translations.

How it works:
- Audit workers store translations in data.i18n[locale] alongside English content
- GET endpoints accept ?locale=fr_fr (or any xx_xx BCP-47 code)
- OpportunityDto promotes i18n[locale].{title,description} to the top-level fields
- SuggestionDto merges i18n[locale] on top of data and strips the i18n key
- Both DTOs strip data.i18n from the response to keep the shape stable
- Missing or absent translations fall back to the original English values

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Sihalnic-Alin Sihalnic-Alin force-pushed the LLMO-5430-unlocalized-strings-in-opportunities branch from bb567f2 to 6167fa0 Compare June 19, 2026 13:16
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