com.xlrit.gears.server.graphql.TranslationResolver Maven / Gradle / Ivy
package com.xlrit.gears.server.graphql;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import jakarta.annotation.PostConstruct;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
@Controller
@RequiredArgsConstructor
public class TranslationResolver {
private static final Logger LOG = LoggerFactory.getLogger(TranslationResolver.class);
private final ObjectMapper objectMapper;
private ObjectNode translationsNode;
@PostConstruct
public void initialize() {
translationsNode = objectMapper.createObjectNode();
loadTranslationResources();
}
private void loadTranslationResources() {
Map> resourcesByLanguage = Arrays.stream(getTranslationResources())
.collect(Collectors.groupingBy(this::getLanguage));
LOG.debug("resourcesByLanguage: {}...", resourcesByLanguage);
resourcesByLanguage.forEach((language, resources) -> {
LOG.info("Loading translations for language '{}'...", language);
ObjectNode languageTranslations = objectMapper.createObjectNode();
for (Resource resource : resources) {
LOG.info("Loading translations from {}...", resource);
merge(languageTranslations, loadTranslationsFrom(resource));
}
translationsNode.set(language, languageTranslations);
});
}
@SneakyThrows
private ObjectNode loadTranslationsFrom(Resource resource) {
try (InputStream is = resource.getInputStream()) {
JsonNode result = objectMapper.readTree(is);
assert result.isObject();
return (ObjectNode) result;
}
}
@SneakyThrows
private String getLanguage(Resource resource) {
String url = resource.getURL().toString();
String[] parts = url.split("/");
return parts[parts.length - 2];
}
@SneakyThrows
private Resource[] getTranslationResources() {
var patternResolver = new PathMatchingResourcePatternResolver();
Resource[] resources = patternResolver.getResources("classpath*:/locales/*/*.json");
LOG.debug("Matched translation resources: {}", (Object) resources);
return resources;
}
@QueryMapping
public JsonNode translations() {
return translationsNode;
}
private static void merge(ObjectNode target, ObjectNode source) {
Iterator fieldNames = source.fieldNames();
while (fieldNames.hasNext()) {
String fieldName = fieldNames.next();
JsonNode sourceValue = source.get(fieldName);
JsonNode targetValue = target.get(fieldName);
if (targetValue == null || targetValue.isNull()) {
target.set(fieldName, sourceValue);
}
else if (targetValue instanceof ObjectNode targetObj && sourceValue instanceof ObjectNode sourceObj) {
merge(targetObj, sourceObj);
}
}
}
}