Skip to content

Commit 99fe5d7

Browse files
committed
[Feature Request] I18n on support. Fixes #1268
1 parent 6e709c9 commit 99fe5d7

34 files changed

+382
-220
lines changed

springdoc-openapi-common/src/main/java/org/springdoc/api/AbstractOpenApiResource.java

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.HashSet;
3636
import java.util.LinkedHashMap;
3737
import java.util.List;
38+
import java.util.Locale;
3839
import java.util.Map;
3940
import java.util.Objects;
4041
import java.util.Optional;
@@ -227,6 +228,13 @@ protected AbstractOpenApiResource(String groupName, ObjectFactory<OpenAPIService
227228
Executors.newSingleThreadExecutor().execute(this::getOpenApi);
228229
}
229230

231+
/**
232+
* Gets open api.
233+
*/
234+
private void getOpenApi() {
235+
this.getOpenApi(Locale.getDefault());
236+
}
237+
230238
/**
231239
* Add rest controllers.
232240
*
@@ -265,14 +273,14 @@ public static void addHiddenRestControllers(String... classes) {
265273

266274
/**
267275
* Gets open api.
268-
*
276+
* @param locale the locale
269277
* @return the open api
270278
*/
271-
protected synchronized OpenAPI getOpenApi() {
279+
protected synchronized OpenAPI getOpenApi(Locale locale) {
272280
OpenAPI openApi;
273281
if (openAPIService.getCachedOpenAPI() == null || springDocConfigProperties.isCacheDisabled()) {
274282
Instant start = Instant.now();
275-
openAPIService.build();
283+
openAPIService.build(locale);
276284
Map<String, Object> mappingsMap = openAPIService.getMappingsMap().entrySet().stream()
277285
.filter(controller -> (AnnotationUtils.findAnnotation(controller.getValue().getClass(),
278286
Hidden.class) == null))
@@ -285,9 +293,9 @@ protected synchronized OpenAPI getOpenApi() {
285293
if (springDocConfigProperties.isOverrideWithGenericResponse() && !CollectionUtils.isEmpty(findControllerAdvice)) {
286294
if (!CollectionUtils.isEmpty(mappingsMap))
287295
findControllerAdvice.putAll(mappingsMap);
288-
responseBuilder.buildGenericResponse(openApi.getComponents(), findControllerAdvice);
296+
responseBuilder.buildGenericResponse(openApi.getComponents(), findControllerAdvice, locale);
289297
}
290-
getPaths(mappingsMap);
298+
getPaths(mappingsMap, locale);
291299
if (!CollectionUtils.isEmpty(openApi.getServers()))
292300
openAPIService.setServersPresent(true);
293301
openAPIService.updateServers(openApi);
@@ -318,16 +326,18 @@ protected synchronized OpenAPI getOpenApi() {
318326
* Gets paths.
319327
*
320328
* @param findRestControllers the find rest controllers
329+
* @param locale the locale
321330
*/
322-
protected abstract void getPaths(Map<String, Object> findRestControllers);
331+
protected abstract void getPaths(Map<String, Object> findRestControllers, Locale locale);
323332

324333
/**
325334
* Calculate path.
326335
*
327336
* @param handlerMethod the handler method
328337
* @param routerOperation the router operation
338+
* @param locale the locale
329339
*/
330-
protected void calculatePath(HandlerMethod handlerMethod, RouterOperation routerOperation) {
340+
protected void calculatePath(HandlerMethod handlerMethod, RouterOperation routerOperation, Locale locale) {
331341
String operationPath = routerOperation.getPath();
332342
Set<RequestMethod> requestMethods = new HashSet<>(Arrays.asList(routerOperation.getMethods()));
333343
io.swagger.v3.oas.annotations.Operation apiOperation = routerOperation.getOperation();
@@ -358,7 +368,7 @@ protected void calculatePath(HandlerMethod handlerMethod, RouterOperation router
358368
RequestMapping reqMappingClass = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(),
359369
RequestMapping.class);
360370

361-
MethodAttributes methodAttributes = new MethodAttributes(springDocConfigProperties.getDefaultConsumesMediaType(), springDocConfigProperties.getDefaultProducesMediaType(), methodConsumes, methodProduces, headers);
371+
MethodAttributes methodAttributes = new MethodAttributes(springDocConfigProperties.getDefaultConsumesMediaType(), springDocConfigProperties.getDefaultProducesMediaType(), methodConsumes, methodProduces, headers, locale);
362372
methodAttributes.setMethodOverloaded(existingOperation != null);
363373
//Use the javadoc return if present
364374
if (javadocProvider != null) {
@@ -389,7 +399,7 @@ protected void calculatePath(HandlerMethod handlerMethod, RouterOperation router
389399
fillParametersList(operation, queryParams, methodAttributes);
390400

391401
// compute tags
392-
operation = openAPIService.buildTags(handlerMethod, operation, openAPI);
402+
operation = openAPIService.buildTags(handlerMethod, operation, openAPI, locale);
393403

394404
io.swagger.v3.oas.annotations.parameters.RequestBody requestBodyDoc = AnnotatedElementUtils.findMergedAnnotation(method,
395405
io.swagger.v3.oas.annotations.parameters.RequestBody.class);
@@ -444,8 +454,9 @@ private void buildCallbacks(OpenAPI openAPI, MethodAttributes methodAttributes,
444454
* Calculate path.
445455
*
446456
* @param routerOperationList the router operation list
457+
* @param locale the locale
447458
*/
448-
protected void calculatePath(List<RouterOperation> routerOperationList) {
459+
protected void calculatePath(List<RouterOperation> routerOperationList, Locale locale) {
449460
ApplicationContext applicationContext = openAPIService.getContext();
450461
if (!CollectionUtils.isEmpty(routerOperationList)) {
451462
Collections.sort(routerOperationList);
@@ -475,14 +486,14 @@ protected void calculatePath(List<RouterOperation> routerOperationList) {
475486
LOGGER.error(e.getMessage());
476487
}
477488
if (handlerMethod != null && isFilterCondition(handlerMethod, routerOperation.getPath(), routerOperation.getProduces(), routerOperation.getConsumes(), routerOperation.getHeaders()))
478-
calculatePath(handlerMethod, routerOperation);
489+
calculatePath(handlerMethod, routerOperation, locale);
479490
}
480491
}
481492
else if (routerOperation.getOperation() != null && StringUtils.isNotBlank(routerOperation.getOperation().operationId()) && isFilterCondition(routerOperation.getPath(), routerOperation.getProduces(), routerOperation.getConsumes(), routerOperation.getHeaders())) {
482-
calculatePath(routerOperation);
493+
calculatePath(routerOperation, locale);
483494
}
484495
else if (routerOperation.getOperationModel() != null && StringUtils.isNotBlank(routerOperation.getOperationModel().getOperationId()) && isFilterCondition(routerOperation.getPath(), routerOperation.getProduces(), routerOperation.getConsumes(), routerOperation.getHeaders())) {
485-
calculatePath(routerOperation);
496+
calculatePath(routerOperation, locale);
486497
}
487498
}
488499
}
@@ -492,8 +503,9 @@ else if (routerOperation.getOperationModel() != null && StringUtils.isNotBlank(r
492503
* Calculate path.
493504
*
494505
* @param routerOperation the router operation
506+
* @param locale the locale
495507
*/
496-
protected void calculatePath(RouterOperation routerOperation) {
508+
protected void calculatePath(RouterOperation routerOperation, Locale locale) {
497509
String operationPath = routerOperation.getPath();
498510
io.swagger.v3.oas.annotations.Operation apiOperation = routerOperation.getOperation();
499511
String[] methodConsumes = routerOperation.getConsumes();
@@ -510,7 +522,7 @@ protected void calculatePath(RouterOperation routerOperation) {
510522
}
511523
for (RequestMethod requestMethod : routerOperation.getMethods()) {
512524
Operation existingOperation = getExistingOperation(operationMap, requestMethod);
513-
MethodAttributes methodAttributes = new MethodAttributes(springDocConfigProperties.getDefaultConsumesMediaType(), springDocConfigProperties.getDefaultProducesMediaType(), methodConsumes, methodProduces, headers);
525+
MethodAttributes methodAttributes = new MethodAttributes(springDocConfigProperties.getDefaultConsumesMediaType(), springDocConfigProperties.getDefaultProducesMediaType(), methodConsumes, methodProduces, headers, locale);
514526
methodAttributes.setMethodOverloaded(existingOperation != null);
515527
Operation operation = getOperation(routerOperation, existingOperation);
516528
if (apiOperation != null)
@@ -541,24 +553,26 @@ protected void calculatePath(RouterOperation routerOperation) {
541553
* @param handlerMethod the handler method
542554
* @param operationPath the operation path
543555
* @param requestMethods the request methods
556+
* @param locale the locale
544557
*/
545558
protected void calculatePath(HandlerMethod handlerMethod, String operationPath,
546-
Set<RequestMethod> requestMethods) {
547-
this.calculatePath(handlerMethod, new RouterOperation(operationPath, requestMethods.toArray(new RequestMethod[requestMethods.size()])));
559+
Set<RequestMethod> requestMethods, Locale locale) {
560+
this.calculatePath(handlerMethod, new RouterOperation(operationPath, requestMethods.toArray(new RequestMethod[requestMethods.size()])), locale);
548561
}
549562

550563
/**
551564
* Gets router function paths.
552565
*
553566
* @param beanName the bean name
554567
* @param routerFunctionVisitor the router function visitor
568+
* @param locale the locale
555569
*/
556-
protected void getRouterFunctionPaths(String beanName, AbstractRouterFunctionVisitor routerFunctionVisitor) {
570+
protected void getRouterFunctionPaths(String beanName, AbstractRouterFunctionVisitor routerFunctionVisitor, Locale locale) {
557571
boolean withRouterOperation = routerFunctionVisitor.getRouterFunctionDatas().stream()
558572
.anyMatch(routerFunctionData -> routerFunctionData.getAttributes().containsKey(OPERATION_ATTRIBUTE));
559573
if (withRouterOperation) {
560574
List<RouterOperation> operationList = routerFunctionVisitor.getRouterFunctionDatas().stream().map(RouterOperation::new).collect(Collectors.toList());
561-
calculatePath(operationList);
575+
calculatePath(operationList, locale);
562576
}
563577
else {
564578
List<org.springdoc.core.annotations.RouterOperation> routerOperationList = new ArrayList<>();
@@ -572,11 +586,11 @@ protected void getRouterFunctionPaths(String beanName, AbstractRouterFunctionVis
572586
else
573587
routerOperationList.addAll(Arrays.asList(routerOperations.value()));
574588
if (routerOperationList.size() == 1)
575-
calculatePath(routerOperationList.stream().map(routerOperation -> new RouterOperation(routerOperation, routerFunctionVisitor.getRouterFunctionDatas().get(0))).collect(Collectors.toList()));
589+
calculatePath(routerOperationList.stream().map(routerOperation -> new RouterOperation(routerOperation, routerFunctionVisitor.getRouterFunctionDatas().get(0))).collect(Collectors.toList()),locale);
576590
else {
577591
List<RouterOperation> operationList = routerOperationList.stream().map(RouterOperation::new).collect(Collectors.toList());
578592
mergeRouters(routerFunctionVisitor.getRouterFunctionDatas(), operationList);
579-
calculatePath(operationList);
593+
calculatePath(operationList, locale);
580594
}
581595
}
582596
}

springdoc-openapi-common/src/main/java/org/springdoc/core/AbstractRequestService.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod,
246246
io.swagger.v3.oas.annotations.Parameter.class);
247247

248248
final String pName = methodParameter.getParameterName();
249-
ParameterInfo parameterInfo = new ParameterInfo(pName, methodParameter, parameterBuilder);
249+
ParameterInfo parameterInfo = new ParameterInfo(pName, methodParameter, parameterBuilder, methodAttributes.getLocale());
250250

251251
if (parameterDoc == null)
252252
parameterDoc = parametersDocMap.get(parameterInfo.getpName());
@@ -255,7 +255,7 @@ public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod,
255255
if (parameterDoc.hidden() || parameterDoc.schema().hidden())
256256
continue;
257257

258-
parameter = parameterBuilder.buildParameterFromDoc(parameterDoc, components, methodAttributes.getJsonViewAnnotation());
258+
parameter = parameterBuilder.buildParameterFromDoc(parameterDoc, components, methodAttributes.getJsonViewAnnotation(), methodAttributes.getLocale());
259259
parameterInfo.setParameterModel(parameter);
260260
}
261261

@@ -322,7 +322,7 @@ private LinkedHashMap<String, Parameter> getParameterLinkedHashMap(Components co
322322
if (entry.getKey() != null && !map.containsKey(entry.getKey()) && !entry.getValue().hidden()) {
323323
//Convert
324324
Parameter parameter = parameterBuilder.buildParameterFromDoc(entry.getValue(), components,
325-
methodAttributes.getJsonViewAnnotation());
325+
methodAttributes.getJsonViewAnnotation(), methodAttributes.getLocale());
326326
map.put(entry.getKey(), parameter);
327327
}
328328
}

springdoc-openapi-common/src/main/java/org/springdoc/core/GenericParameterService.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.Arrays;
2929
import java.util.HashMap;
3030
import java.util.List;
31+
import java.util.Locale;
3132
import java.util.Map;
3233
import java.util.Optional;
3334

@@ -198,15 +199,16 @@ private static void mergeParameter(Parameter paramCalcul, Parameter paramDoc) {
198199
* @param parameterDoc the parameter doc
199200
* @param components the components
200201
* @param jsonView the json view
202+
* @param locale the locale
201203
* @return the parameter
202204
*/
203205
public Parameter buildParameterFromDoc(io.swagger.v3.oas.annotations.Parameter parameterDoc,
204-
Components components, JsonView jsonView) {
206+
Components components, JsonView jsonView, Locale locale) {
205207
Parameter parameter = new Parameter();
206208
if (StringUtils.isNotBlank(parameterDoc.description()))
207-
parameter.setDescription(propertyResolverUtils.resolve(parameterDoc.description()));
209+
parameter.setDescription(propertyResolverUtils.resolve(parameterDoc.description(),locale));
208210
if (StringUtils.isNotBlank(parameterDoc.name()))
209-
parameter.setName(propertyResolverUtils.resolve(parameterDoc.name()));
211+
parameter.setName(propertyResolverUtils.resolve(parameterDoc.name(),locale));
210212
if (StringUtils.isNotBlank(parameterDoc.in().toString()))
211213
parameter.setIn(parameterDoc.in().toString());
212214
if (StringUtils.isNotBlank(parameterDoc.example())) {

springdoc-openapi-common/src/main/java/org/springdoc/core/GenericResponseService.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.HashSet;
3030
import java.util.LinkedHashMap;
3131
import java.util.List;
32+
import java.util.Locale;
3233
import java.util.Map;
3334
import java.util.Objects;
3435
import java.util.Optional;
@@ -150,8 +151,9 @@ public ApiResponses build(Components components, HandlerMethod handlerMethod, Op
150151
*
151152
* @param components the components
152153
* @param findControllerAdvice the find controller advice
154+
* @param locale the locale
153155
*/
154-
public void buildGenericResponse(Components components, Map<String, Object> findControllerAdvice) {
156+
public void buildGenericResponse(Components components, Map<String, Object> findControllerAdvice, Locale locale) {
155157
// ControllerAdvice
156158
for (Map.Entry<String, Object> entry : findControllerAdvice.entrySet()) {
157159
List<Method> methods = new ArrayList<>();
@@ -177,7 +179,7 @@ public void buildGenericResponse(Components components, Map<String, Object> find
177179
MethodParameter methodParameter = new MethodParameter(method, -1);
178180
ApiResponses apiResponsesOp = new ApiResponses();
179181
MethodAttributes methodAttributes = new MethodAttributes(methodProduces, springDocConfigProperties.getDefaultConsumesMediaType(),
180-
springDocConfigProperties.getDefaultProducesMediaType(), controllerAdviceInfoApiResponseMap);
182+
springDocConfigProperties.getDefaultProducesMediaType(), controllerAdviceInfoApiResponseMap, locale);
181183
//calculate JsonView Annotation
182184
methodAttributes.setJsonViewAnnotation(AnnotatedElementUtils.findMergedAnnotation(method, JsonView.class));
183185
//use the javadoc return if present
@@ -237,7 +239,7 @@ private Map<String, ApiResponse> computeResponseFromDoc(Components components, M
237239
apiResponsesOp.addApiResponse(apiResponseAnnotations.responseCode(), apiResponse);
238240
continue;
239241
}
240-
apiResponse.setDescription(propertyResolverUtils.resolve(apiResponseAnnotations.description()));
242+
apiResponse.setDescription(propertyResolverUtils.resolve(apiResponseAnnotations.description(),methodAttributes.getLocale()));
241243
buildContentFromDoc(components, apiResponsesOp, methodAttributes, apiResponseAnnotations, apiResponse);
242244
Map<String, Object> extensions = AnnotationsUtils.getExtensions(apiResponseAnnotations.extensions());
243245
if (!CollectionUtils.isEmpty(extensions))

springdoc-openapi-common/src/main/java/org/springdoc/core/MethodAttributes.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import java.lang.reflect.Method;
2424
import java.util.LinkedHashMap;
25+
import java.util.Locale;
2526
import java.util.Map;
2627

2728
import com.fasterxml.jackson.annotation.JsonView;
@@ -112,46 +113,54 @@ public class MethodAttributes {
112113
*/
113114
private String javadocReturn;
114115

116+
/**
117+
* The Locale.
118+
*/
119+
private final Locale locale;
120+
115121
/**
116122
* Instantiates a new Method attributes.
117-
*
118123
* @param methodProducesNew the method produces new
119124
* @param defaultConsumesMediaType the default consumes media type
120125
* @param defaultProducesMediaType the default produces media type
121126
* @param genericMapResponse the generic map response
127+
* @param locale the locale
122128
*/
123-
public MethodAttributes(String[] methodProducesNew, String defaultConsumesMediaType, String defaultProducesMediaType, Map<String, ApiResponse> genericMapResponse) {
129+
public MethodAttributes(String[] methodProducesNew, String defaultConsumesMediaType, String defaultProducesMediaType, Map<String, ApiResponse> genericMapResponse, Locale locale) {
124130
this.methodProduces = methodProducesNew;
125131
this.defaultConsumesMediaType = defaultConsumesMediaType;
126132
this.defaultProducesMediaType = defaultProducesMediaType;
127133
this.genericMapResponse = genericMapResponse;
134+
this.locale = locale;
128135
}
129136

130137
/**
131138
* Instantiates a new Method attributes.
132-
*
133139
* @param defaultConsumesMediaType the default consumes media type
134140
* @param defaultProducesMediaType the default produces media type
141+
* @param locale the locale
135142
*/
136-
public MethodAttributes(String defaultConsumesMediaType, String defaultProducesMediaType) {
143+
public MethodAttributes(String defaultConsumesMediaType, String defaultProducesMediaType, Locale locale) {
137144
this.defaultConsumesMediaType = defaultConsumesMediaType;
138145
this.defaultProducesMediaType = defaultProducesMediaType;
146+
this.locale = locale;
139147
}
140148

141149
/**
142150
* Instantiates a new Method attributes.
143-
*
144151
* @param defaultConsumesMediaType the default consumes media type
145152
* @param defaultProducesMediaType the default produces media type
146153
* @param methodConsumes the method consumes
147154
* @param methodProduces the method produces
148155
* @param headers the headers
156+
* @param locale the locale
149157
*/
150-
public MethodAttributes(String defaultConsumesMediaType, String defaultProducesMediaType, String[] methodConsumes, String[] methodProduces, String[] headers) {
158+
public MethodAttributes(String defaultConsumesMediaType, String defaultProducesMediaType, String[] methodConsumes, String[] methodProduces, String[] headers, Locale locale) {
151159
this.defaultConsumesMediaType = defaultConsumesMediaType;
152160
this.defaultProducesMediaType = defaultProducesMediaType;
153161
this.methodProduces = methodProduces;
154162
this.methodConsumes = methodConsumes;
163+
this.locale = locale;
155164
setHeaders(headers);
156165
}
157166

@@ -443,4 +452,13 @@ public String getJavadocReturn() {
443452
public void setJavadocReturn(String javadocReturn) {
444453
this.javadocReturn = javadocReturn;
445454
}
455+
456+
/**
457+
* Gets locale.
458+
*
459+
* @return the locale
460+
*/
461+
public Locale getLocale() {
462+
return locale;
463+
}
446464
}

0 commit comments

Comments
 (0)