Skip to content

Available languages API v2#3911

Open
jmendeza wants to merge 1 commit intocraftercms:developfrom
jmendeza:feature/6061-lang
Open

Available languages API v2#3911
jmendeza wants to merge 1 commit intocraftercms:developfrom
jmendeza:feature/6061-lang

Conversation

@jmendeza
Copy link
Copy Markdown
Member

@jmendeza jmendeza commented Apr 1, 2026

Available languages API v2
craftercms/craftercms#6061

Summary by CodeRabbit

  • New Features

    • Added a new API endpoint to retrieve available system languages.
    • Added configurable system setting for available languages (English, Español, 한국어, Deutsch).
  • Chores

    • Removed the legacy language endpoint and migrated to the new API path.
    • Updated the security allowlist to expose the new endpoint.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

Warning

Rate limit exceeded

@jmendeza has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 14 minutes and 23 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 14 minutes and 23 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 29f77edb-ded3-43fa-937f-cee9e3861baa

📥 Commits

Reviewing files that changed from the base of the PR and between 977705d and c2c8f20.

📒 Files selected for processing (10)
  • src/main/api/studio-api.yaml
  • src/main/java/org/craftercms/studio/api/v2/service/config/ConfigurationService.java
  • src/main/java/org/craftercms/studio/api/v2/utils/StudioConfiguration.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/RequestMappingConstants.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/ResultConstants.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/SystemController.java
  • src/main/java/org/craftercms/studio/impl/v2/service/configuration/ConfigurationServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v2/service/configuration/internal/ConfigurationServiceInternalImpl.java
  • src/main/java/org/craftercms/studio/model/i18n/Language.java
  • src/main/resources/crafter/studio/studio-config.yaml

Walkthrough

Adds a new GET /api/2/system/available_languages endpoint, introduces a Language record, extends configuration service and implementations to expose available languages, updates SystemController and routing/result constants, and adds studio configuration entries plus security URL updates for the new endpoint.

Changes

Cohort / File(s) Summary
API Specification
src/main/api/studio-api.yaml
Removed legacy v1 GET /api/1/.../get-available-languages.json; added v2 GET /api/2/system/available_languages with structured response and languages payload and shared error responses.
Data Model
src/main/java/org/craftercms/studio/model/i18n/Language.java
Added Language record with String id and String label.
Service API & Impl
src/main/java/org/craftercms/studio/api/v2/service/config/ConfigurationService.java, src/main/java/org/craftercms/studio/impl/v2/service/configuration/ConfigurationServiceImpl.java
Added Collection<Language> getAvailableLanguages() throws ServiceLayerException to the interface and a thin delegating implementation in the service impl.
Service Internal
src/main/java/org/craftercms/studio/impl/v2/service/configuration/internal/ConfigurationServiceInternalImpl.java
Implemented getAvailableLanguages() using configurationCache.get(..., this::loadAvailableLanguages), added loadAvailableLanguages() to read studio.configuration.availableLanguages, extract id/label, and build Language collection; added related constants and imports.
Controller & Constants
src/main/java/org/craftercms/studio/controller/rest/v2/SystemController.java, src/main/java/org/craftercms/studio/controller/rest/v2/RequestMappingConstants.java, src/main/java/org/craftercms/studio/controller/rest/v2/ResultConstants.java
SystemController constructor now accepts ConfigurationService; added getAvailableLanguages() endpoint returning ResultList<Language>; added AVAILABLE_LANGUAGES mapping and RESULT_KEY_LANGUAGES key.
Configuration & Security
src/main/resources/crafter/studio/studio-config.yaml, src/main/java/org/craftercms/studio/api/v2/utils/StudioConfiguration.java
Added studio.configuration.availableLanguages entries (en, es, ko, de); updated studio.security.publicUrls to allow /api/2/system/available_languages and removed legacy v1 patterns; added CONFIGURATION_AVAILABLE_LANGUAGES constant.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant SystemController
    participant ConfigurationService
    participant ConfigurationServiceInternal
    participant ConfigurationCache
    participant StudioConfiguration

    Client->>SystemController: GET /api/2/system/available_languages
    SystemController->>ConfigurationService: getAvailableLanguages()
    ConfigurationService->>ConfigurationServiceInternal: getAvailableLanguages()
    ConfigurationServiceInternal->>ConfigurationCache: get(CONFIGURATION_AVAILABLE_LANGUAGES, loader)
    alt cache hit
        ConfigurationCache-->>ConfigurationServiceInternal: Collection<Language>
    else cache miss
        ConfigurationServiceInternal->>StudioConfiguration: getSubConfigs(CONFIGURATION_AVAILABLE_LANGUAGES)
        StudioConfiguration-->>ConfigurationServiceInternal: List<config nodes>
        ConfigurationServiceInternal->>ConfigurationServiceInternal: loadAvailableLanguages() (extract id,label)
        ConfigurationServiceInternal->>ConfigurationCache: store Collection<Language>
        ConfigurationCache-->>ConfigurationServiceInternal: Collection<Language>
    end
    ConfigurationServiceInternal-->>ConfigurationService: Collection<Language>
    ConfigurationService-->>SystemController: Collection<Language>
    SystemController-->>Client: 200 OK { response: {...}, languages: [...] }
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: implementing a new v2 API endpoint for retrieving available languages.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/main/java/org/craftercms/studio/api/v2/service/config/ConfigurationService.java (1)

267-272: Consider documenting the checked exception in the new API contract.

For consistency with the rest of this interface, add an @throws ServiceLayerException line in this method’s Javadoc.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/org/craftercms/studio/api/v2/service/config/ConfigurationService.java`
around lines 267 - 272, Add an `@throws` ServiceLayerException Javadoc tag to the
getAvailableLanguages() method in the ConfigurationService interface so the
checked exception is documented in the API contract; update the Javadoc block
above the method declaration (the comment for getAvailableLanguages) to include
a line like "@throws ServiceLayerException if an error occurs in the service
layer" so the interface consistently documents checked exceptions.
src/main/resources/crafter/studio/studio-config.yaml (1)

364-365: Remove duplicated forgot-password public URL pattern.

/api/2/users/forgot_password.* appears twice across Line 364 and Line 365. Keeping one improves maintainability with no behavior change.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/crafter/studio/studio-config.yaml` around lines 364 - 365,
The public URL patterns list contains a duplicate entry of the same
forgot-password regex '/api/2/users/forgot_password.*'; remove the duplicated
occurrence so the list only contains a single '/api/2/users/forgot_password.*'
entry (leave the other patterns like '/api/2/monitoring/.+' and
'/api/2/users/set_password.*' unchanged) to improve maintainability.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/api/studio-api.yaml`:
- Around line 8197-8224: The operation getAvailableLanguages in the OpenAPI
contract is advertised as "No permission required" but still inherits file-level
auth; update the operation (operationId: getAvailableLanguages) to include
security: [] to mark it as public and remove the '401' and '403' response
entries from this operation's responses so the spec matches the documented
public behavior; keep the '200' (and other non-auth-related responses like '500'
if applicable) intact.

In
`@src/main/java/org/craftercms/studio/impl/v2/service/configuration/internal/ConfigurationServiceInternalImpl.java`:
- Around line 731-753: getAvailableLanguages currently returns the cached
collection directly and loadAvailableLanguages builds a mutable ArrayList,
exposing shared mutable state via configurationCache and
CONFIGURATION_AVAILABLE_LANGUAGES; change loadAvailableLanguages to return an
unmodifiable collection (e.g., wrap the final List with
Collections.unmodifiableList) and ensure getAvailableLanguages does not return
the cached mutable instance directly (either cache the unmodifiable collection
or return a defensive copy) so callers cannot mutate the cached languages;
reference the methods getAvailableLanguages, loadAvailableLanguages and the
configurationCache/CONFIGURATION_AVAILABLE_LANGUAGES keys when making the
change.

In `@src/main/resources/crafter/studio/studio-config.yaml`:
- Line 363: The public-URL regex entry for the available languages endpoint is
an exact path and will not match query-string variants; update the string
"/api/2/system/available_languages" in the studio-config.yaml public URL list to
a regex that allows query strings (e.g., append ".*") so it reads
"/api/2/system/available_languages.*" (preserve the trailing comma and
surrounding list format) to prevent accidental auth requirements for requests
like /api/2/system/available_languages?...

---

Nitpick comments:
In
`@src/main/java/org/craftercms/studio/api/v2/service/config/ConfigurationService.java`:
- Around line 267-272: Add an `@throws` ServiceLayerException Javadoc tag to the
getAvailableLanguages() method in the ConfigurationService interface so the
checked exception is documented in the API contract; update the Javadoc block
above the method declaration (the comment for getAvailableLanguages) to include
a line like "@throws ServiceLayerException if an error occurs in the service
layer" so the interface consistently documents checked exceptions.

In `@src/main/resources/crafter/studio/studio-config.yaml`:
- Around line 364-365: The public URL patterns list contains a duplicate entry
of the same forgot-password regex '/api/2/users/forgot_password.*'; remove the
duplicated occurrence so the list only contains a single
'/api/2/users/forgot_password.*' entry (leave the other patterns like
'/api/2/monitoring/.+' and '/api/2/users/set_password.*' unchanged) to improve
maintainability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b56857f2-5087-426f-bae7-663044826830

📥 Commits

Reviewing files that changed from the base of the PR and between 4adf04e and ef00753.

📒 Files selected for processing (10)
  • src/main/api/studio-api.yaml
  • src/main/java/org/craftercms/studio/api/v2/service/config/ConfigurationService.java
  • src/main/java/org/craftercms/studio/api/v2/utils/StudioConfiguration.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/RequestMappingConstants.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/ResultConstants.java
  • src/main/java/org/craftercms/studio/controller/rest/v2/SystemController.java
  • src/main/java/org/craftercms/studio/impl/v2/service/configuration/ConfigurationServiceImpl.java
  • src/main/java/org/craftercms/studio/impl/v2/service/configuration/internal/ConfigurationServiceInternalImpl.java
  • src/main/java/org/craftercms/studio/model/i18n/Language.java
  • src/main/resources/crafter/studio/studio-config.yaml

@jmendeza jmendeza force-pushed the feature/6061-lang branch 3 times, most recently from ce65196 to 108eec6 Compare April 1, 2026 02:44
@jmendeza jmendeza force-pushed the feature/6061-lang branch from 108eec6 to c2c8f20 Compare April 1, 2026 02:46
@jmendeza jmendeza marked this pull request as ready for review April 1, 2026 02:48
@jmendeza jmendeza requested a review from sumerjabri as a code owner April 1, 2026 02:48
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.

1 participant