Merge branch 'local' of git://github.com/honzapatCZ/FlaxEngine into honzapatCZ-local
# Conflicts: # Source/Editor/Windows/Assets/LocalizedStringTableWindow.cs # Source/Engine/Localization/Localization.cpp # Source/Engine/Localization/LocalizedStringTable.h
This commit is contained in:
@@ -176,7 +176,6 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
allKeys.Add(e.Key);
|
||||
}
|
||||
}
|
||||
_valueElement.TextBox.SetTextAsUser(null);
|
||||
string newKey = null;
|
||||
if (string.IsNullOrEmpty(_idElement.Text))
|
||||
{
|
||||
@@ -216,17 +215,19 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
var newValue = _valueElement.Text;
|
||||
Editor.Log(newKey + (newValue != null ? " = " + newValue : string.Empty));
|
||||
var locales = settings.LocalizedStringTables.GroupBy(x => x.Locale);
|
||||
var defaultLocale = settings.LocalizedStringTables[0].Locale;
|
||||
foreach (var locale in locales)
|
||||
{
|
||||
var table = locale.First();
|
||||
var entries = table.Entries;
|
||||
if (table.Locale == "en")
|
||||
if (table.Locale == defaultLocale)
|
||||
entries[newKey] = new[] { newValue };
|
||||
else
|
||||
entries[newKey] = new[] { string.Empty };
|
||||
table.Entries = entries;
|
||||
table.Save();
|
||||
}
|
||||
_valueElement.TextBox.SetTextAsUser(null);
|
||||
_idElement.TextBox.SetTextAsUser(newKey);
|
||||
Profiler.EndEvent();
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
CultureInfo CurrentCulture;
|
||||
CultureInfo CurrentLanguage;
|
||||
Array<AssetReference<LocalizedStringTable>> LocalizedStringTables;
|
||||
Array<AssetReference<LocalizedStringTable>> FallbackStringTables;
|
||||
|
||||
LocalizationService()
|
||||
: EngineService(TEXT("Localization"), -500)
|
||||
@@ -28,6 +29,42 @@ public:
|
||||
|
||||
void OnLocalizationChanged();
|
||||
|
||||
const String& Get(const String& id, int32 index, const String& fallback) const
|
||||
{
|
||||
if (id.IsEmpty())
|
||||
return fallback;
|
||||
|
||||
// Try current tables
|
||||
for (auto& e : LocalizedStringTables)
|
||||
{
|
||||
const auto table = e.Get();
|
||||
const auto messages = table ? table->Entries.TryGet(id) : nullptr;
|
||||
if (messages && messages->Count() > index)
|
||||
return messages->At(index);
|
||||
}
|
||||
|
||||
// Try fallback tables for current tables
|
||||
for (auto& e : LocalizedStringTables)
|
||||
{
|
||||
const auto table = e.Get();
|
||||
const auto fallbackTable = table ? table->FallbackTable.Get() : nullptr;
|
||||
const auto messages = fallbackTable ? fallbackTable->Entries.TryGet(id) : nullptr;
|
||||
if (messages && messages->Count() > index)
|
||||
return messages->At(index);
|
||||
}
|
||||
|
||||
// Try fallback language tables
|
||||
for (auto& e : FallbackStringTables)
|
||||
{
|
||||
const auto table = e.Get();
|
||||
const auto messages = table ? table->Entries.TryGet(id) : nullptr;
|
||||
if (messages && messages->Count() > index)
|
||||
return messages->At(index);
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
bool Init() override;
|
||||
};
|
||||
|
||||
@@ -46,6 +83,7 @@ void LocalizationSettings::Apply()
|
||||
void LocalizationSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
||||
{
|
||||
DESERIALIZE(LocalizedStringTables);
|
||||
DESERIALIZE(DefaultFallbackLanguage);
|
||||
}
|
||||
|
||||
LocalizedString::LocalizedString(const LocalizedString& other)
|
||||
@@ -119,10 +157,12 @@ void LocalizationService::OnLocalizationChanged()
|
||||
PROFILE_CPU();
|
||||
|
||||
Instance.LocalizedStringTables.Clear();
|
||||
Instance.FallbackStringTables.Clear();
|
||||
const StringView en(TEXT("en"));
|
||||
|
||||
// Collect all localization tables into mapping locale -> tables
|
||||
auto& settings = *LocalizationSettings::Get();
|
||||
Dictionary<String, Array<AssetReference<LocalizedStringTable>, InlinedAllocation<8>>> tables;
|
||||
Dictionary<String, Array<AssetReference<LocalizedStringTable>, InlinedAllocation<32>>> tables;
|
||||
for (auto& e : settings.LocalizedStringTables)
|
||||
{
|
||||
auto table = e.Get();
|
||||
@@ -142,9 +182,13 @@ void LocalizationService::OnLocalizationChanged()
|
||||
table = tables.TryGet(parentLanguage.GetName());
|
||||
if (!table)
|
||||
{
|
||||
// Fallback to English
|
||||
const CultureInfo english("en");
|
||||
table = tables.TryGet(english.GetName());
|
||||
// Fallback to Default
|
||||
table = tables.TryGet(settings.DefaultFallbackLanguage);
|
||||
if (!table)
|
||||
{
|
||||
// Fallback to English
|
||||
table = tables.TryGet(en);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +206,17 @@ void LocalizationService::OnLocalizationChanged()
|
||||
}
|
||||
LOG(Info, "Using localization for {0}", locale);
|
||||
Instance.LocalizedStringTables.Add(table->Get(), table->Count());
|
||||
if (locale != settings.DefaultFallbackLanguage || locale != en)
|
||||
{
|
||||
// Cache fallback language tables to support additional text resolving in case of missing entries in the current language
|
||||
table = tables.TryGet(settings.DefaultFallbackLanguage);
|
||||
if (!table)
|
||||
table = tables.TryGet(en);
|
||||
if (table)
|
||||
{
|
||||
Instance.FallbackStringTables.Add(table->Get(), table->Count());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if PLATFORM_ANDROID
|
||||
@@ -193,8 +248,12 @@ void LocalizationService::OnLocalizationChanged()
|
||||
{
|
||||
std::locale::global(std::locale(localeName));
|
||||
}
|
||||
catch (std::runtime_error const&) {}
|
||||
catch (...) {}
|
||||
catch (std::runtime_error const&)
|
||||
{
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -258,68 +317,12 @@ void Localization::SetCurrentLanguageCulture(const CultureInfo& value)
|
||||
|
||||
String Localization::GetString(const String& id, const String& fallback)
|
||||
{
|
||||
const String* result = nullptr;
|
||||
for (auto& e : Instance.LocalizedStringTables)
|
||||
{
|
||||
const auto table = e.Get();
|
||||
const auto messages = table ? table->Entries.TryGet(id) : nullptr;
|
||||
if (messages && messages->Count() != 0)
|
||||
{
|
||||
result = &messages->At(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
// Try using fallback tables
|
||||
for (auto& e : Instance.LocalizedStringTables)
|
||||
{
|
||||
const auto table = e.Get();
|
||||
const auto fallbackTable = table ? table->FallbackTable.Get() : nullptr;
|
||||
const auto messages = fallbackTable ? fallbackTable->Entries.TryGet(id) : nullptr;
|
||||
if (messages && messages->Count() != 0)
|
||||
{
|
||||
result = &messages->At(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result)
|
||||
result = &fallback;
|
||||
return *result;
|
||||
return Instance.Get(id, 0, fallback);
|
||||
}
|
||||
|
||||
String Localization::GetPluralString(const String& id, int32 n, const String& fallback)
|
||||
{
|
||||
CHECK_RETURN(n >= 1, fallback);
|
||||
n--;
|
||||
const String* result = nullptr;
|
||||
for (auto& e : Instance.LocalizedStringTables)
|
||||
{
|
||||
const auto table = e.Get();
|
||||
const auto messages = table ? table->Entries.TryGet(id) : nullptr;
|
||||
if (messages && messages->Count() > n)
|
||||
{
|
||||
result = &messages->At(n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
// Try using fallback tables
|
||||
for (auto& e : Instance.LocalizedStringTables)
|
||||
{
|
||||
const auto table = e.Get();
|
||||
const auto fallbackTable = table ? table->FallbackTable.Get() : nullptr;
|
||||
const auto messages = fallbackTable ? fallbackTable->Entries.TryGet(id) : nullptr;
|
||||
if (messages && messages->Count() > n)
|
||||
{
|
||||
result = &messages->At(n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result)
|
||||
result = &fallback;
|
||||
return String::Format(result->GetText(), n);
|
||||
CHECK_RETURN(n >= 1, String::Format(fallback.GetText(), n));
|
||||
const String& format = Instance.Get(id, n - 1, fallback);
|
||||
return String::Format(format.GetText(), n);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/// </summary>
|
||||
API_CLASS(Static) class FLAXENGINE_API Localization
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(Localization);
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(Localization);
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the current culture (date, time, currency and values formatting locale).
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/// </summary>
|
||||
API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API LocalizationSettings : public SettingsBase
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(LocalizationSettings);
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(LocalizationSettings);
|
||||
public:
|
||||
/// <summary>
|
||||
/// The list of the string localization tables used by the game.
|
||||
@@ -19,6 +19,12 @@ public:
|
||||
API_FIELD()
|
||||
Array<AssetReference<LocalizedStringTable>> LocalizedStringTables;
|
||||
|
||||
/// <summary>
|
||||
/// The default fallback language to use if localization system fails to pick the system locale language (eg. en-GB).
|
||||
/// </summary>
|
||||
API_FIELD()
|
||||
String DefaultFallbackLanguage;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use.
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace FlaxEngine
|
||||
/// <returns>The localized text.</returns>
|
||||
public string ToStringPlural(int n)
|
||||
{
|
||||
return string.IsNullOrEmpty(Value) ? Localization.GetPluralString(Id, n) : Value;
|
||||
return string.IsNullOrEmpty(Value) ? Localization.GetPluralString(Id, n) : string.Format(Value, n);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -33,6 +33,28 @@ void LocalizedStringTable::AddPluralString(const StringView& id, const StringVie
|
||||
values[n] = value;
|
||||
}
|
||||
|
||||
String LocalizedStringTable::GetString(const String& id) const
|
||||
{
|
||||
StringView result;
|
||||
const auto messages = Entries.TryGet(id);
|
||||
if (messages && messages->Count() != 0)
|
||||
result = messages->At(0);
|
||||
if (result.IsEmpty() && FallbackTable)
|
||||
result = FallbackTable->GetString(id);
|
||||
return result;
|
||||
}
|
||||
|
||||
String LocalizedStringTable::GetPluralString(const String& id, int32 n) const
|
||||
{
|
||||
StringView result;
|
||||
const auto messages = Entries.TryGet(id);
|
||||
if (messages && messages->Count() > n)
|
||||
result = messages->At(n);
|
||||
if (result.IsEmpty() && FallbackTable)
|
||||
result = FallbackTable->GetPluralString(id, n);
|
||||
return String::Format(result.GetNonTerminatedText(), n);
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
bool LocalizedStringTable::Save(const StringView& path)
|
||||
|
||||
@@ -13,9 +13,8 @@
|
||||
/// <seealso cref="JsonAssetBase" />
|
||||
API_CLASS(NoSpawn) class FLAXENGINE_API LocalizedStringTable : public JsonAssetBase
|
||||
{
|
||||
DECLARE_ASSET_HEADER(LocalizedStringTable);
|
||||
DECLARE_ASSET_HEADER(LocalizedStringTable);
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// The locale of the localized string table (eg. pl-PL).
|
||||
/// </summary>
|
||||
@@ -32,7 +31,6 @@ public:
|
||||
API_FIELD() Dictionary<String, Array<String>> Entries;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Adds the localized string to the table.
|
||||
/// </summary>
|
||||
@@ -48,6 +46,21 @@ public:
|
||||
/// <param name="n">The plural value (0, 1, 2..).</param>
|
||||
API_FUNCTION() void AddPluralString(const StringView& id, const StringView& value, int32 n);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the localized string by using string id lookup. Uses fallback table if text is not included in this table.
|
||||
/// </summary>
|
||||
/// <param name="id">The message identifier.</param>
|
||||
/// <returns>The localized text.</returns>
|
||||
API_FUNCTION() String GetString(const String& id) const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the localized plural string by using string id lookup. Uses fallback table if text is not included in this table.
|
||||
/// </summary>
|
||||
/// <param name="id">The message identifier.</param>
|
||||
/// <param name="n">The value count for plural message selection.</param>
|
||||
/// <returns>The localized text.</returns>
|
||||
API_FUNCTION() String GetPluralString(const String& id, int32 n) const;
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user