-
Notifications
You must be signed in to change notification settings - Fork 422
Localisation
Localisation in osu-framework
revolves around the LocalisableString
class, which UI controls and text destinations accept in place of string
. This page explains the provided methods of interacting with LocalisableString
, but further customisation is also possible by implementing ILocalisableStringData
directly.
Represents a string which can be formatted based on the currently selected locale, exposed in two methods and one extension method:
-
LocalisableString.Format
, accepting a format string and a list of arguments designed in a similar fashion tostring.Format
:// Text = string.Format("{0} + {1} = {2}", localisable1, localisable2, localisable3); Text = LocalisableString.Format("{0} + {1} = {2}", localisable1, localisable2, localisable3);
-
LocalisableString.Interpolate
, accepting an interpolated string ($"..."
):// Text = $"{localisable1} + {localisable2} = {localisable3}"; Text = LocalisableString.Interpolate($"{localisable1} + {localisable2} = {localisable3}");
-
LocalisableStringExtensions.ToLocalisableString
, accepting anIFormattable
object (e.g. number types,DateTime
s,TimeSpan
s, etc.) and a format string, in a similar fashion toIFomrattable.ToString
:// Text = formattable.ToString("N0"); Text = formattable.ToLocalisableString("N0");
Represents a string which can be translated across different languages via a specific "key" that is used to look up on the ILocalisationStore
associated with the locale.
Text = new TranslatableString("music_string_key", "music");
string Get(string lookup) // ILocalisationStore.Get(string)
{
if (lookup == "music_string_key")
{
switch (EffectiveCulture.Name)
{
case "en": return "music";
case "ja": return "音楽";
...
}
}
}
In addition, TranslatableString
s support formatting, allowing for the translated strings to specify placeholder items which are replaced with the given arguments list, in a similar fashion to string.Format
/LocalisableString.Format
.
Text = new TranslatableString("music_string_key", "{0} music", number.ToLocalisableString("0.00%"));
string Get(string lookup) // ILocalisationStore.Get(string)
{
if (lookup == "music_string_key")
{
switch (EffectiveCulture.Name)
{
case "en": return "{0} music";
case "ja": return "音楽 {0}";
...
}
}
}
Represents a unicode string that has a romanised variant, in which can be toggled on/off by the FrameworkSetting.ShowUnicode
setting available in the config manager.
Text = new RomanisableString("音楽", "ongaku");
// FrameworkSetting.ShowUnicode == true: "音楽" is shown
// FrameworkSetting.ShowUnicode == false: "ongaku" is shown
Represents a string which accepts a LocalisableString
and transforms it to the specified casing, exposed in a set of extension methods which accept either LocalisableString
or ILocalisableStringData
(string implementations):
-
LocalisableStringExtensions.ToUpper
, which converts all characters of the input string to uppercase, usingTextInfo.ToUpper
. -
LocalisableStringExtensions.ToLower
, which converts all characters of the input string to lowercase, usingTextInfo.ToLower
. -
LocalisableStringExtensions.ToTitle
, which converts the first character of every word to uppercase while the rest to lowercase, usingTextInfo.ToTitleCase
.
It's implemented in a way that allows it to build itself over a LocalisableString
or any string implementation:
Text = LocalisableString.Format($"{localisable1} -> {localisable2}").ToUpper();
Text = new RomanisableString("音楽", "ongaku").ToTitle();
...
LocalisableString
accepts any implementation that confronts to the ILocalisableStringData
interface, in which it can retrieve the final localised string with.
public class CustomLocalisableString : IEquatable<CustomLocalisableString>, ILocalisableStringData
{
public string GetLocalised(LocalisationParameters parameters)
{
return /* localisation logic */;
}
public bool Equals(CustomLocalisableString other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return /* equality */;
}
public bool Equals(ILocalisableStringData other) => other is CustomLocalisableString custom && Equals(custom);
public override bool Equals(object? obj) => obj is CustomLocalisableString custom && Equals(custom);
public override int GetHashCode() => /* hash code */;
}
String implementations require context to be able to localise the string. LocalisationParameters
provide enough context to fit the need for the framework's own string implementations, but it can be built upon for custom string implementations.
This can be achieved by creating a LocalisationManager
subclass that overrides the LocalisationParameters
factory method and calls UpdateLocalisationParameters
to update the parameters:
public class CustomLocalisationManager : LocalisationManager
{
private readonly IBindable<int> custom = new BindableInt();
public CustomLocalisationManager(FrameworkConfigManager frameworkConfig, CustomConfigManager config)
: base(frameworkConfig)
{
config.BindWith(CustomSetting.Custom, custom);
custom.BindValueChanged(_ => UpdateLocalisationParameters(), true);
}
protected override LocalisationParameters CreateLocalisationParameters() => new CustomLocalisationParameters(base.CreateLocalisationParameters(), custom.Value);
protected class CustomLocalisationParameters : LocalisationParameters
{
public readonly int Custom;
protected CustomLocalisationParameters(CustomLocalisationParameters parameters)
: base(parameters, parameters.Custom)
{
}
public CustomLocalisationParameters(LocalisationParameters parameters, int custom)
: base(parameters)
{
Custom = custom;
}
}
}
public string GetLocalised(LocalisationParameters parameters)
{
var customParameters = (CustomLocalisationParameters)parameters;
return /* localisation logic */;
}
Represents an attribute for assigning localised description strings to classes/enums, similar to DescriptionAttribute
.
Since attributes in general only allow constant input, the LocalisableString
s to use for the attribute must be stored statically in a public field or a property:
public static class Strings
{
public static LocalisableString Class => ...;
public static LocalisableString EnumOne => ...;
public static LocalisableString EnumTwo => ...;
public static LocalisableString EnumThree => ...;
}
The way LocalisableDescriptionAttribute
works is by specifying the Type
of the class containing the LocalisableString
member, followed by the name of said member for lookup:
// [Description("Class")]
[LocalisableDescription(typeof(Strings), nameof(Strings.Class))]
public class ClassWithLocalisableDescription
{
}
public enum EnumWithLocalisableDescription
{
// [Description("One")]
[LocalisableDescription(typeof(Strings), nameof(Strings.EnumOne))]
One,
// [Description("Two")]
[LocalisableDescription(typeof(Strings), nameof(Strings.EnumTwo))]
Two,
// [Description("Three")]
[LocalisableDescription(typeof(Strings), nameof(Strings.EnumThree))]
Three,
}
And in order to retrieve the description, use the extension method ExtensionMethods.GetLocalisableDescription
:
// Text = classInstance.GetDescription();
Text = classInstance.GetLocalisableDescription();
// Text = enumValue.GetDescription();
Text = enumValue.GetLocalisableDescription();
- Create your first project
- Learning framework key bindings
- Adding resource stores
- Adding custom key bindings
- Adding custom fonts