From cf3c537e30870be4488246d7024a7f0b14018406 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 4 Dec 2023 11:13:12 +0100 Subject: [PATCH 1/4] Add a way to get the key of a `TranslatableString` encapsulated by a `LocalisableString` Since `Data` is `internal`, a helper method is needed. --- .../LocalisableStringExtensions.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osu.Framework/Extensions/LocalisationExtensions/LocalisableStringExtensions.cs b/osu.Framework/Extensions/LocalisationExtensions/LocalisableStringExtensions.cs index 012097af06..7479a57982 100644 --- a/osu.Framework/Extensions/LocalisationExtensions/LocalisableStringExtensions.cs +++ b/osu.Framework/Extensions/LocalisationExtensions/LocalisableStringExtensions.cs @@ -70,5 +70,22 @@ public static class LocalisableStringExtensions /// The string data. /// A case transformable string with its string data transformed to sentence case. public static CaseTransformableString ToSentence(this ILocalisableStringData data) => new LocalisableString(data).ToSentence(); + + /// + /// Returns the of the that is the underlying data of this . + /// + /// + /// The whose underlying data is the . + /// This is usually a static property of a "strings" class containing translation definitions. + /// + /// The of the underlying . + /// Thrown if this doesn't have underlying data. + public static string GetKey(this LocalisableString str) + { + if (str.Data is not TranslatableString translatable) + throw new ArgumentException($"The {nameof(LocalisableString)} doesn't have underlying {nameof(TranslatableString)} data.", nameof(str)); + + return translatable.Key; + } } } From 000c7c2e35603457a066e030e120cf2da7cd0d95 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 4 Dec 2023 11:16:12 +0100 Subject: [PATCH 2/4] Add a simple example of translating framework-side strings The shape of `WindowModeStrings.cs` modelled after osu! localisations. --- .../TestSceneFrameworkStringLocalisation.cs | 57 +++++++++++++++++++ osu.Framework/Configuration/WindowMode.cs | 8 +++ .../Localisation/Strings/WindowModeStrings.cs | 27 +++++++++ 3 files changed, 92 insertions(+) create mode 100644 osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs create mode 100644 osu.Framework/Localisation/Strings/WindowModeStrings.cs diff --git a/osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs b/osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs new file mode 100644 index 0000000000..b594928939 --- /dev/null +++ b/osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs @@ -0,0 +1,57 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation.Strings; + +namespace osu.Framework.Tests.Visual.Localisation +{ + public partial class TestSceneFrameworkStringLocalisation : LocalisationTestScene + { + [BackgroundDependencyLoader] + private void load() + { + Manager.AddLanguage("en-US", new TestLocalisationStore("en-US", new Dictionary + { + // no translations, use the fallback value + })); + + Manager.AddLanguage("en-GB", new TestLocalisationStore("en-GB", new Dictionary + { + [WindowModeStrings.Windowed.GetKey()] = "Windowed", + [WindowModeStrings.Borderless.GetKey()] = "Borderless", + [WindowModeStrings.Fullscreen.GetKey()] = "Full screen", + })); + + Manager.AddLanguage("hr-HR", new TestLocalisationStore("hr-HR", new Dictionary + { + [WindowModeStrings.Windowed.GetKey()] = "Prozor", + [WindowModeStrings.Borderless.GetKey()] = "Bez ruba", + [WindowModeStrings.Fullscreen.GetKey()] = "Puni zaslon", + })); + } + + [Test] + public void TestDropdown() + { + AddStep("add dropdown", () => + { + Child = new BasicDropdown + { + Width = 200, + Items = Enum.GetValues() + }; + }); + + SetLocale("en-US"); + SetLocale("en-GB"); + SetLocale("hr-HR"); + } + } +} diff --git a/osu.Framework/Configuration/WindowMode.cs b/osu.Framework/Configuration/WindowMode.cs index 54db687231..e4050436e2 100644 --- a/osu.Framework/Configuration/WindowMode.cs +++ b/osu.Framework/Configuration/WindowMode.cs @@ -1,12 +1,20 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Localisation; +using osu.Framework.Localisation.Strings; + namespace osu.Framework.Configuration { public enum WindowMode { + [LocalisableDescription(typeof(WindowModeStrings), nameof(WindowModeStrings.Windowed))] Windowed = 0, + + [LocalisableDescription(typeof(WindowModeStrings), nameof(WindowModeStrings.Borderless))] Borderless = 1, + + [LocalisableDescription(typeof(WindowModeStrings), nameof(WindowModeStrings.Fullscreen))] Fullscreen = 2 } } diff --git a/osu.Framework/Localisation/Strings/WindowModeStrings.cs b/osu.Framework/Localisation/Strings/WindowModeStrings.cs new file mode 100644 index 0000000000..3c17cbe32b --- /dev/null +++ b/osu.Framework/Localisation/Strings/WindowModeStrings.cs @@ -0,0 +1,27 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Framework.Localisation.Strings +{ + public static class WindowModeStrings + { + private const string prefix = "osu.Framework.Resources.Localisation.WindowMode"; + + /// + /// "Windowed" + /// + public static LocalisableString Windowed => new TranslatableString(getKey("windowed"), "Windowed"); + + /// + /// "Borderless" + /// + public static LocalisableString Borderless => new TranslatableString(getKey("borderless"), "Borderless"); + + /// + /// "Fullscreen" + /// + public static LocalisableString Fullscreen => new TranslatableString(getKey("fullscreen"), "Fullscreen"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} From c39d52e71781095b701c676be4cf8a9fd767df9e Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 4 Dec 2023 11:51:29 +0100 Subject: [PATCH 3/4] Rename extension method to `GetTranslationKey()` Since the extension method is intended for a very specific use case, the name `GetKey()` felt too generic. --- .../TestSceneFrameworkStringLocalisation.cs | 12 ++++++------ .../LocalisableStringExtensions.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs b/osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs index b594928939..8109ac7f83 100644 --- a/osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs +++ b/osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs @@ -24,16 +24,16 @@ private void load() Manager.AddLanguage("en-GB", new TestLocalisationStore("en-GB", new Dictionary { - [WindowModeStrings.Windowed.GetKey()] = "Windowed", - [WindowModeStrings.Borderless.GetKey()] = "Borderless", - [WindowModeStrings.Fullscreen.GetKey()] = "Full screen", + [WindowModeStrings.Windowed.GetTranslationKey()] = "Windowed", + [WindowModeStrings.Borderless.GetTranslationKey()] = "Borderless", + [WindowModeStrings.Fullscreen.GetTranslationKey()] = "Full screen", })); Manager.AddLanguage("hr-HR", new TestLocalisationStore("hr-HR", new Dictionary { - [WindowModeStrings.Windowed.GetKey()] = "Prozor", - [WindowModeStrings.Borderless.GetKey()] = "Bez ruba", - [WindowModeStrings.Fullscreen.GetKey()] = "Puni zaslon", + [WindowModeStrings.Windowed.GetTranslationKey()] = "Prozor", + [WindowModeStrings.Borderless.GetTranslationKey()] = "Bez ruba", + [WindowModeStrings.Fullscreen.GetTranslationKey()] = "Puni zaslon", })); } diff --git a/osu.Framework/Extensions/LocalisationExtensions/LocalisableStringExtensions.cs b/osu.Framework/Extensions/LocalisationExtensions/LocalisableStringExtensions.cs index 7479a57982..d4ef372c90 100644 --- a/osu.Framework/Extensions/LocalisationExtensions/LocalisableStringExtensions.cs +++ b/osu.Framework/Extensions/LocalisationExtensions/LocalisableStringExtensions.cs @@ -80,7 +80,7 @@ public static class LocalisableStringExtensions /// /// The of the underlying . /// Thrown if this doesn't have underlying data. - public static string GetKey(this LocalisableString str) + public static string GetTranslationKey(this LocalisableString str) { if (str.Data is not TranslatableString translatable) throw new ArgumentException($"The {nameof(LocalisableString)} doesn't have underlying {nameof(TranslatableString)} data.", nameof(str)); From d8db21c9da5784210037e6c8955f4c2f1e53e14d Mon Sep 17 00:00:00 2001 From: Susko3 Date: Mon, 4 Dec 2023 12:18:11 +0100 Subject: [PATCH 4/4] Improve tests --- .../Localisation/TestSceneFrameworkStringLocalisation.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs b/osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs index 8109ac7f83..b44a059ba3 100644 --- a/osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs +++ b/osu.Framework.Tests/Visual/Localisation/TestSceneFrameworkStringLocalisation.cs @@ -38,17 +38,19 @@ private void load() } [Test] - public void TestDropdown() + public void TestEnumDropdown() { + BasicDropdown dropdown = null!; + AddStep("add dropdown", () => { - Child = new BasicDropdown + Child = dropdown = new BasicDropdown { Width = 200, Items = Enum.GetValues() }; }); - + AddStep("open dropdown", () => dropdown.Menu.Open()); SetLocale("en-US"); SetLocale("en-GB"); SetLocale("hr-HR");