From 5cab52c48d79ca1151adf36aef570654f3a9da1a Mon Sep 17 00:00:00 2001 From: MEFRREEX Date: Tue, 18 Nov 2025 21:56:51 +0400 Subject: [PATCH 1/2] feat: implement missing language strategies --- README.md | 18 +++++-- .../luminiadev/polyglot/api/Translation.java | 3 ++ .../api/util/LanguageMappingBuilder.java | 20 ++++++++ .../polyglot/api/util/LanguageStrategy.java | 50 +++++++++++++++++++ .../polyglot/core/BaseTranslation.java | 20 ++++++++ 5 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 api/src/main/java/com/luminiadev/polyglot/api/util/LanguageMappingBuilder.java create mode 100644 api/src/main/java/com/luminiadev/polyglot/api/util/LanguageStrategy.java diff --git a/README.md b/README.md index 9fb5529..e2780fd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Polyglot -Polyglot is an advanced and multifunctional library for localizing strings for Luminia Development projects. +Polyglot is an advanced and multifunctional library for localizing strings. ## Example of usage ```java @@ -26,12 +26,24 @@ Translation translation = context.createTranslation(new YamlFileProvider( new File("lang"), context.getLanguageStandard() )); translation.setDefaultLanguage(SimpleLanguage.ENG); // Default language -translation.setFallbackStrategy(key -> key + "-fallback"); // Fallback strategy for missing localizations + +// Strategy for determining the language when the requested language is not available. +// For example: return Russian when Ukrainian is not available, instead of the default English. +translation.setLanguageStrategy(LanguageStrategy.mappings() + .put(SimpleLanguage.UKR, SimpleLanguage.RUS) + .build()); +// We can also set the default language using `LanguageStrategy.defaultResult(SimpleLanguage.ENG)`. + +// Fallback strategy for missing localizations +// You can also do the same thing this way: `translation.setFallbackStrategy(FallbackStrategy.suffix(“-fallback”));`. +// Or you can use `FallbackStrategy.keyToKey()` if you want the result to be the key of the missing locale. +translation.setFallbackStrategy(key -> key + "-fallback"); + translation.addTranslation(SimpleLanguage.ENG, "local.translation", "Local message with param [0]"); // Adding local translation // Translating the messages String local = translation.translate(SimpleLanguage.RUS, "local.translation", 1); -String global = translation.translate(SimpleLanguage.RUS, "local.translation", new KeyedTrParameters().put("local", "Parameter")); +String global = translation.translate(SimpleLanguage.RUS, "global.translation", new KeyedTrParameters().put("local", "Parameter")); System.out.println("Translated local message: " + local); System.out.println("Translated global message: " + global); diff --git a/api/src/main/java/com/luminiadev/polyglot/api/Translation.java b/api/src/main/java/com/luminiadev/polyglot/api/Translation.java index f8778f7..c4e72d1 100644 --- a/api/src/main/java/com/luminiadev/polyglot/api/Translation.java +++ b/api/src/main/java/com/luminiadev/polyglot/api/Translation.java @@ -4,6 +4,7 @@ import com.luminiadev.polyglot.api.parameter.TrParameters; import com.luminiadev.polyglot.api.parameter.formatter.TrParameterFormatter; import com.luminiadev.polyglot.api.util.FallbackStrategy; +import com.luminiadev.polyglot.api.util.LanguageStrategy; import java.util.Set; @@ -19,6 +20,8 @@ public interface Translation { void setDefaultLanguage(Language language); + void setLanguageStrategy(LanguageStrategy languageStrategy); + void setFallbackStrategy(FallbackStrategy fallbackStrategy); void addTranslation(Language language, String key, String value); diff --git a/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageMappingBuilder.java b/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageMappingBuilder.java new file mode 100644 index 0000000..70d5960 --- /dev/null +++ b/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageMappingBuilder.java @@ -0,0 +1,20 @@ +package com.luminiadev.polyglot.api.util; + +import com.luminiadev.polyglot.api.language.Language; + +import java.util.HashMap; +import java.util.Map; + +public final class LanguageMappingBuilder { + + private final Map mappings = new HashMap<>(); + + public LanguageMappingBuilder put(Language missingLanguage, Language mappedLanguage) { + this.mappings.put(missingLanguage, mappedLanguage); + return this; + } + + public LanguageStrategy build() { + return LanguageStrategy.mappings(mappings); + } +} diff --git a/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageStrategy.java b/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageStrategy.java new file mode 100644 index 0000000..6ea5730 --- /dev/null +++ b/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageStrategy.java @@ -0,0 +1,50 @@ +package com.luminiadev.polyglot.api.util; + +import com.luminiadev.polyglot.api.language.Language; + +import java.util.Map; + +/** + * Missing language strategy interface. Defines how to resolve missing language. + */ +@FunctionalInterface +public interface LanguageStrategy { + + /** + * Resolves a value for the given missing language. + * + * @param missingLanguage the missing language + * @return resolved value + */ + Language get(Language missingLanguage); + + /** + * Returns a default language. + * + * @param defaultLanguage default language + * @return strategy returning the specified language + */ + static LanguageStrategy defaultResult(Language defaultLanguage) { + return missingLanguage -> defaultLanguage; + } + + /** + * Returns a strategy based on passed mappings. + * + * @param mappings the map with language mappings + * @return strategy based on passed mappings + */ + static LanguageStrategy mappings(Map mappings) { + return missingLanguage -> mappings.getOrDefault(missingLanguage, null); + } + + /** + * Crates the new language mappings builder. + * + * @return crated LanguageMappingBuilder + */ + static LanguageMappingBuilder mappings() { + return new LanguageMappingBuilder(); + } +} + diff --git a/core/src/main/java/com/luminiadev/polyglot/core/BaseTranslation.java b/core/src/main/java/com/luminiadev/polyglot/core/BaseTranslation.java index 948ae76..2595f14 100644 --- a/core/src/main/java/com/luminiadev/polyglot/core/BaseTranslation.java +++ b/core/src/main/java/com/luminiadev/polyglot/core/BaseTranslation.java @@ -7,6 +7,7 @@ import com.luminiadev.polyglot.api.parameter.TrParameters; import com.luminiadev.polyglot.api.parameter.formatter.TrParameterFormatter; import com.luminiadev.polyglot.api.provider.TranslationProvider; +import com.luminiadev.polyglot.api.util.LanguageStrategy; import com.luminiadev.polyglot.core.parameter.KeyedTrParameters; import com.luminiadev.polyglot.core.parameter.SimpleTrParameters; import com.luminiadev.polyglot.core.parameter.formatter.BraceKeyedParameterFormatter; @@ -27,6 +28,7 @@ public class BaseTranslation implements Translation { private final Map, TrParameterFormatter> formatters; private Language defaultLanguage; + private LanguageStrategy languageStrategy; private FallbackStrategy fallbackStrategy; public BaseTranslation(TranslationContext context, TranslationProvider provider) { @@ -70,10 +72,23 @@ private Language resolveLanguage(Language requestedLanguage) { if (this.isLanguageAvailable(requestedLanguage)) { return requestedLanguage; } + + Language candidateLanguage = requestedLanguage; + while (true) { + candidateLanguage = this.languageStrategy != null ? this.languageStrategy.get(candidateLanguage) : null; + if (candidateLanguage == null) { + break; + } + if (this.isLanguageAvailable(candidateLanguage)) { + return candidateLanguage; + } + } + Language defaultLanguage = this.defaultLanguage != null ? this.defaultLanguage : context.getDefaultLanguage(); if (this.isLanguageAvailable(defaultLanguage)) { return defaultLanguage; } + return requestedLanguage; } @@ -163,6 +178,11 @@ public void setDefaultLanguage(Language language) { this.defaultLanguage = language; } + @Override + public void setLanguageStrategy(LanguageStrategy languageStrategy) { + this.languageStrategy = languageStrategy; + } + @Override public void setFallbackStrategy(FallbackStrategy fallbackStrategy) { this.fallbackStrategy = fallbackStrategy; From 99307e5a9f35b745127373c28d8d2da8c98dd5d1 Mon Sep 17 00:00:00 2001 From: MEFRREEX Date: Tue, 18 Nov 2025 21:59:02 +0400 Subject: [PATCH 2/2] refactor: rename LanguageStrategy.mappings() to LanguageStrategy.mappingsBuilder() --- README.md | 2 +- .../luminiadev/polyglot/api/util/LanguageMappingBuilder.java | 2 +- .../com/luminiadev/polyglot/api/util/LanguageStrategy.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e2780fd..301abfa 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ translation.setDefaultLanguage(SimpleLanguage.ENG); // Default language // Strategy for determining the language when the requested language is not available. // For example: return Russian when Ukrainian is not available, instead of the default English. -translation.setLanguageStrategy(LanguageStrategy.mappings() +translation.setLanguageStrategy(LanguageStrategy.mappingsBuilder() .put(SimpleLanguage.UKR, SimpleLanguage.RUS) .build()); // We can also set the default language using `LanguageStrategy.defaultResult(SimpleLanguage.ENG)`. diff --git a/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageMappingBuilder.java b/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageMappingBuilder.java index 70d5960..b94253b 100644 --- a/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageMappingBuilder.java +++ b/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageMappingBuilder.java @@ -15,6 +15,6 @@ public LanguageMappingBuilder put(Language missingLanguage, Language mappedLangu } public LanguageStrategy build() { - return LanguageStrategy.mappings(mappings); + return LanguageStrategy.mappingsOf(mappings); } } diff --git a/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageStrategy.java b/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageStrategy.java index 6ea5730..f609095 100644 --- a/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageStrategy.java +++ b/api/src/main/java/com/luminiadev/polyglot/api/util/LanguageStrategy.java @@ -34,7 +34,7 @@ static LanguageStrategy defaultResult(Language defaultLanguage) { * @param mappings the map with language mappings * @return strategy based on passed mappings */ - static LanguageStrategy mappings(Map mappings) { + static LanguageStrategy mappingsOf(Map mappings) { return missingLanguage -> mappings.getOrDefault(missingLanguage, null); } @@ -43,7 +43,7 @@ static LanguageStrategy mappings(Map mappings) { * * @return crated LanguageMappingBuilder */ - static LanguageMappingBuilder mappings() { + static LanguageMappingBuilder mappingsBuilder() { return new LanguageMappingBuilder(); } }