From 79d1d0c1096673f6b07f7bc29fd547b501923955 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 8 Apr 2026 09:46:59 +0200 Subject: [PATCH] Add `Localization.GetLocales` to list all languages in a game --- Source/Engine/Localization/Localization.cpp | 57 ++++++++++++++++++++ Source/Engine/Localization/Localization.h | 6 +++ Source/Engine/Localization/LocalizedString.h | 45 +--------------- 3 files changed, 65 insertions(+), 43 deletions(-) diff --git a/Source/Engine/Localization/Localization.cpp b/Source/Engine/Localization/Localization.cpp index d1b3a036f..acc265025 100644 --- a/Source/Engine/Localization/Localization.cpp +++ b/Source/Engine/Localization/Localization.cpp @@ -169,6 +169,50 @@ String LocalizedString::ToStringPlural(int32 n) const return Localization::GetPluralString(Id, n, Value); } +void Serialization::Serialize(ISerializable::SerializeStream& stream, const LocalizedString& v, const void* otherObj) +{ + if (v.Id.IsEmpty()) + { + stream.String(v.Value); + } + else + { + stream.StartObject(); + stream.JKEY("Id"); + stream.String(v.Id); + if (v.Value.HasChars()) + { + stream.JKEY("Value"); + stream.String(v.Value); + } + stream.EndObject(); + } +} + +void Serialization::Deserialize(ISerializable::DeserializeStream& stream, LocalizedString& v, ISerializeModifier* modifier) +{ + if (stream.IsString()) + { + v.Id = String::Empty; + v.Value = stream.GetText(); + } + else if (stream.IsObject()) + { + auto e = SERIALIZE_FIND_MEMBER(stream, "Id"); + if (e != stream.MemberEnd()) + v.Id.SetUTF8(e->value.GetString(), e->value.GetStringLength()); + e = SERIALIZE_FIND_MEMBER(stream, "Value"); + if (e != stream.MemberEnd()) + v.Value.SetUTF8(e->value.GetString(), e->value.GetStringLength()); + else if (v.Id.HasChars()) + v.Value.Clear(); + } + else + { + v = LocalizedString(); + } +} + void LocalizationService::OnLocalizationChanged() { PROFILE_CPU(); @@ -346,3 +390,16 @@ String Localization::GetPluralString(const String& id, int32 n, const String& fa const String& format = Instance.Get(id, n - 1, fallback); return String::Format(format.GetText(), n); } + +Array Localization::GetLocales() +{ + Array result; + auto& settings = *LocalizationSettings::Get(); + for (auto& e : settings.LocalizedStringTables) + { + auto table = e.Get(); + if (table && !table->WaitForLoaded()) + result.AddUnique(table->Locale); + } + return result; +} diff --git a/Source/Engine/Localization/Localization.h b/Source/Engine/Localization/Localization.h index 277052c2f..05cd5115f 100644 --- a/Source/Engine/Localization/Localization.h +++ b/Source/Engine/Localization/Localization.h @@ -59,4 +59,10 @@ public: /// The optional fallback string value to use if localized string is missing. /// The localized text. API_FUNCTION() static String GetPluralString(const String& id, int32 n, const String& fallback = String::Empty); + + /// + /// Gets the list of unique languages (locale names such as 'pl-PL') defined in project in Localized String Tables set in Localization Settings. Can be used to display all languages available in game. + /// + /// The list of unique languages (locale names such as 'pl-PL'). + API_FUNCTION() static Array GetLocales(); }; diff --git a/Source/Engine/Localization/LocalizedString.h b/Source/Engine/Localization/LocalizedString.h index 15aee439f..7f660827f 100644 --- a/Source/Engine/Localization/LocalizedString.h +++ b/Source/Engine/Localization/LocalizedString.h @@ -71,49 +71,8 @@ namespace Serialization return !otherObj || v != *(LocalizedString*)otherObj; } - inline void Serialize(ISerializable::SerializeStream& stream, const LocalizedString& v, const void* otherObj) - { - if (v.Id.IsEmpty()) - { - stream.String(v.Value); - } - else - { - stream.StartObject(); - stream.JKEY("Id"); - stream.String(v.Id); - if (v.Value.HasChars()) - { - stream.JKEY("Value"); - stream.String(v.Value); - } - stream.EndObject(); - } - } - - inline void Deserialize(ISerializable::DeserializeStream& stream, LocalizedString& v, ISerializeModifier* modifier) - { - if (stream.IsString()) - { - v.Id = String::Empty; - v.Value = stream.GetText(); - } - else if (stream.IsObject()) - { - auto e = SERIALIZE_FIND_MEMBER(stream, "Id"); - if (e != stream.MemberEnd()) - v.Id.SetUTF8(e->value.GetString(), e->value.GetStringLength()); - e = SERIALIZE_FIND_MEMBER(stream, "Value"); - if (e != stream.MemberEnd()) - v.Value.SetUTF8(e->value.GetString(), e->value.GetStringLength()); - else if (v.Id.HasChars()) - v.Value.Clear(); - } - else - { - v = LocalizedString(); - } - } + FLAXENGINE_API void Serialize(ISerializable::SerializeStream& stream, const LocalizedString& v, const void* otherObj); + FLAXENGINE_API void Deserialize(ISerializable::DeserializeStream& stream, LocalizedString& v, ISerializeModifier* modifier); } DEFINE_DEFAULT_FORMATTING_VIA_TO_STRING(LocalizedString);