For the current version, translation support should be split into two layers:
- translation of wrapper-owned UI in this gem
- optional extension points for deeper Swagger UI component overrides
The recommended first implementation is to support only the UI text owned by grape-swagger-rails itself and explicitly avoid promising full upstream Swagger UI localization.
Why
The current codebase vendors Swagger UI 5.32.5, but Swagger UI does not appear to expose a stable, officially documented localization API suitable for this gem to depend on.
Relevant upstream context:
Because of that, built-in “full translation support” would require this gem to own a fragile override layer tied to Swagger UI internals.
Recommended Scope
Phase 1: Translate wrapper-owned UI
Add translation support only for text rendered or controlled directly by grape-swagger-rails, for example:
- theme toggle label
- spec selector label
- API key input placeholder or label when controlled by the wrapper
- page title fallback such as
Swagger
This is low-risk and fully under local control.
Phase 2: Expose extension points for deeper Swagger UI overrides
Do not attempt to fully localize all upstream Swagger UI text out of the box.
Instead:
- keep built-in translation support limited to wrapper UI
- document how advanced users can inject Swagger UI plugins through
swagger_ui_config
- optionally provide a minimal plugin hook for targeted component overrides later
Proposed API
Suggested options:
GrapeSwaggerRails.options.locale = :en
GrapeSwaggerRails.options.translations = {
en: {
theme_toggle_dark: 'Dark Mode',
theme_toggle_light: 'Light Mode',
spec_selector: 'Specification',
api_key_placeholder: 'api_key',
page_title: 'Swagger'
},
fr: {
theme_toggle_dark: 'Mode sombre',
theme_toggle_light: 'Mode clair',
spec_selector: 'Spécification',
api_key_placeholder: 'clé_api',
page_title: 'Swagger'
}
}
Optional request-time locale resolution:
GrapeSwaggerRails.options.locale_resolver = ->(request) { I18n.locale }
This is preferable to a Rails-I18n-only design because:
- it keeps the gem self-contained
- it works in simpler host apps
- it allows a later Rails-I18n fallback without breaking the public API
Implementation Shape
Ruby options
Add new options:
locale
locale_resolver
translations
Controller/helper layer
Resolve the active locale per request and serialize the active translation dictionary into HTML data-* attributes.
Example helper payload:
{
swagger_options: options.marshal_dump.to_json,
swagger_locale: resolved_locale,
swagger_translations: resolved_translations.to_json
}
Frontend layer
In frontend/grape_swagger_rails/index.ts:
- read
swaggerTranslations from document.documentElement.dataset
- add a small translation helper
Example:
function t(key: string, fallback: string): string {
return translations[key] || fallback;
}
Use it only for wrapper-owned UI:
- theme toggle label
- spec selector label
- placeholders
- title fallback when needed
Deeper Swagger UI Localization
If deeper localization is needed later, build it as an extension point rather than a blanket built-in feature.
The repo already supports:
GrapeSwaggerRails.options.swagger_ui_config = {
plugins: [ ... ]
}
The practical next step would be to document how host applications can inject Swagger UI plugins that override selected React components.
If the gem itself eventually provides built-in localized component overrides, keep that list intentionally small and limited to stable surfaces.
Possible candidates:
InfoContainer
- auth-related labels if stable override points exist
- selected top-level headings
What to Avoid
- Do not patch or rewrite vendored
swagger-ui-bundle.js for translation purposes.
- Do not promise full localization support in the README unless the gem actually maintains a tested override layer across Swagger UI upgrades.
- Do not couple the design only to Rails
I18n.t; keep Rails I18n optional.
Recommended Rollout
- Add wrapper-level translation support only.
- Document that internal Swagger UI strings remain upstream-controlled.
- Document the existing
swagger_ui_config plugin escape hatch for advanced customization.
- Consider a small built-in localized component override layer only if there is demonstrated demand.
Suggested README Wording
grape-swagger-rails supports translation of the wrapper UI it owns (page chrome, labels, toggles, placeholders).
Internal Swagger UI text is controlled by upstream Swagger UI and is not fully localized by this gem.
Advanced users can inject Swagger UI plugins via swagger_ui_config to override additional components.
For the current version, translation support should be split into two layers:
The recommended first implementation is to support only the UI text owned by
grape-swagger-railsitself and explicitly avoid promising full upstream Swagger UI localization.Why
The current codebase vendors Swagger UI
5.32.5, but Swagger UI does not appear to expose a stable, officially documented localization API suitable for this gem to depend on.Relevant upstream context:
Because of that, built-in “full translation support” would require this gem to own a fragile override layer tied to Swagger UI internals.
Recommended Scope
Phase 1: Translate wrapper-owned UI
Add translation support only for text rendered or controlled directly by
grape-swagger-rails, for example:SwaggerThis is low-risk and fully under local control.
Phase 2: Expose extension points for deeper Swagger UI overrides
Do not attempt to fully localize all upstream Swagger UI text out of the box.
Instead:
swagger_ui_configProposed API
Suggested options:
Optional request-time locale resolution:
This is preferable to a Rails-I18n-only design because:
Implementation Shape
Ruby options
Add new options:
localelocale_resolvertranslationsController/helper layer
Resolve the active locale per request and serialize the active translation dictionary into HTML
data-*attributes.Example helper payload:
Frontend layer
In
frontend/grape_swagger_rails/index.ts:swaggerTranslationsfromdocument.documentElement.datasetExample:
Use it only for wrapper-owned UI:
Deeper Swagger UI Localization
If deeper localization is needed later, build it as an extension point rather than a blanket built-in feature.
The repo already supports:
The practical next step would be to document how host applications can inject Swagger UI plugins that override selected React components.
If the gem itself eventually provides built-in localized component overrides, keep that list intentionally small and limited to stable surfaces.
Possible candidates:
InfoContainerWhat to Avoid
swagger-ui-bundle.jsfor translation purposes.I18n.t; keep Rails I18n optional.Recommended Rollout
swagger_ui_configplugin escape hatch for advanced customization.Suggested README Wording