Compare commits

..
Author SHA1 Message Date
Turret 08af14a890 Translated using Weblate (Polish)
Currently translated at 100.0% (77 of 77 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/pl/
2026-10-20 14:19:07 +00:00
Anonymous e2a3dc782b Translated using Weblate (Russian)
Currently translated at 12.9% (10 of 77 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/ru/
2026-10-19 06:19:07 +00:00
Anonymous 109dc796c5 Translated using Weblate (French)
Currently translated at 12.9% (10 of 77 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/fr/
2026-10-19 06:19:07 +00:00
10 changed files with 79 additions and 151 deletions

No files matched your search

@@ -14,13 +14,8 @@ public sealed class ModdedOptionChangedAttribute(string? methodName = null, Type
{
internal Delegate? GetChanged(AbstractOptionGroup group, PropertyInfo property, IModdedOption option)
{
if (ResolveMethod(group, property, out var type, out var instanceGetter, out var notFound) is not { } method)
{
if (notFound)
Error($"Method {MemberName} does not exist in {type.FullName}");
if (ResolveMethod(group, property, out var type, out var instanceGetter) is not { } method)
return null;
}
var valueType = option.GetValueType();
@@ -33,13 +28,8 @@ public sealed class ModdedOptionChangedAttribute(string? methodName = null, Type
internal Func<int, Delegate?>? GetListChanged(AbstractOptionGroup group, PropertyInfo property, Type valueType)
{
if (ResolveMethod(group, property, out var type, out var instanceGetter, out var notFound) is not { } method)
{
if (notFound)
Error($"Method {MemberName} does not exist in {type.FullName}");
if (ResolveMethod(group, property, out var type, out var instanceGetter) is not { } method)
return null;
}
if (!ValidateListSignature(method, typeof(void), out var hasIndex, valueType))
return null;
@@ -14,13 +14,8 @@ public sealed class ModdedOptionGetterAttribute(string? methodName = null, Type?
{
internal Delegate? GetGetter(AbstractOptionGroup group, PropertyInfo property, IModdedOption option)
{
if (ResolveMethod(group, property, out var type, out var instanceGetter, out var notFound) is not { } method)
{
if (notFound)
Error($"Method {MemberName} does not exist in {type.FullName}");
if (ResolveMethod(group, property, out var type, out var instanceGetter) is not { } method)
return null;
}
var valueType = option.GetValueType();
@@ -33,13 +28,8 @@ public sealed class ModdedOptionGetterAttribute(string? methodName = null, Type?
internal Func<int, Delegate?>? GetListGetter(AbstractOptionGroup group, PropertyInfo property, Type valueType)
{
if (ResolveMethod(group, property, out var type, out var instanceGetter, out var notFound) is not { } method)
{
if (notFound)
Error($"Method {MemberName} does not exist in {type.FullName}");
if (ResolveMethod(group, property, out var type, out var instanceGetter) is not { } method)
return null;
}
if (!ValidateListSignature(method, valueType, out var hasIndex, valueType))
return null;
@@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using MiraAPI.Utilities;
namespace MiraAPI.GameOptions.Attributes;
@@ -128,7 +127,7 @@ public abstract class ModdedOptionMemberAttribute(string? memberName, Type? hold
}
/// <summary>
/// Resolves the target <see cref="MemberInfo"/> (property, field or method) and its associated singleton instance getter, if applicable.
/// Resolves the target <see cref="MemberInfo"/> (property or method) and its associated singleton instance getter, if applicable.
/// </summary>
/// <param name="group">The option group instance the property belongs to.</param>
/// <param name="property">The option property decorated with this attribute.</param>
@@ -137,18 +136,15 @@ public abstract class ModdedOptionMemberAttribute(string? memberName, Type? hold
/// When this method returns, contains the <see cref="OptionGroupSingleton{T}.Instance"/> getter <see cref="MethodInfo"/>
/// if the resolved member is an instance member on an <see cref="AbstractOptionGroup"/>; otherwise, <see langword="null"/>.
/// </param>
/// <param name="notFound">When this method returns, contains a flag that indicates if the member was not found, as null can be returned from other circumstances too.</param>
/// <returns>The resolved <see cref="MemberInfo"/> if found; otherwise, <see langword="null"/>.</returns>
[SuppressMessage("Major Code Smell", "S3011:Reflection should not be used to increase accessibility of classes, methods, or fields", Justification = "It is safe.")]
protected MemberInfo? ResolveMember(AbstractOptionGroup group, PropertyInfo property, out Type type, out MethodInfo? instanceGetter, out bool notFound)
protected MemberInfo? ResolveMember(AbstractOptionGroup group, PropertyInfo property, out Type type, out MethodInfo? instanceGetter)
{
var groupType = group.GetType();
var flags = BindingFlags.Static | BindingFlags.Public;
MemberName ??= property.Name + defaultSuffix;
type = holderType ?? groupType;
instanceGetter = null;
MemberName ??= property.Name + defaultSuffix;
if (type.IsAssignableTo(typeof(AbstractOptionGroup)))
{
@@ -162,69 +158,12 @@ public abstract class ModdedOptionMemberAttribute(string? memberName, Type? hold
.GetProperty(nameof(OptionGroupSingleton<>.Instance))!
.GetGetMethod();
}
else if (!type.IsStatic())
else
{
flags |= BindingFlags.Instance;
var canSearchPrivates = type.GetCustomAttribute<SearchPrivateAttribute>() != null;
if (canSearchPrivates)
flags |= BindingFlags.NonPublic;
var getterFlags = BindingFlags.Static | BindingFlags.Public | (canSearchPrivates ? BindingFlags.NonPublic : BindingFlags.Default);
foreach (var method in type.GetMethods(getterFlags))
{
if (method.GetParameters().Length > 0 || (method.GetCustomAttribute<InstanceGetterAttribute>() == null && method.Name != "GetInstance"))
continue;
instanceGetter = method;
break;
}
if (instanceGetter == null)
{
foreach (var prop in type.GetProperties(getterFlags))
{
if (prop.GetCustomAttribute<InstanceGetterAttribute>() == null && prop.Name != "Instance")
continue;
var getMethod = prop.GetGetMethod(canSearchPrivates);
if (getMethod == null)
continue;
instanceGetter = getMethod;
break;
}
}
if (instanceGetter == null)
{
Error($"No valid static instance getter (method GetInstance or property Instance) found in instanced type {type.Name}. Try renaming the method/property, or decorate it with InstanceGetterAttribute.");
notFound = false;
return null;
}
if (!instanceGetter.ReturnType.IsAssignableTo(type))
{
Error($"Found instance getter {instanceGetter.Name}, but the return type did not match what was expected ({type.Name}).");
notFound = false;
return null;
}
}
else if (type.GetCustomAttribute<SearchPrivateAttribute>() != null)
{
flags |= BindingFlags.NonPublic;
instanceGetter = null;
}
var member = type.GetMember(MemberName, flags).FirstOrDefault();
notFound = true;
if (member == null)
return null;
notFound = false;
if (instanceGetter == null)
return member;
@@ -257,11 +196,10 @@ public abstract class ModdedOptionMemberAttribute(string? memberName, Type? hold
/// When this method returns, contains the <see cref="OptionGroupSingleton{T}.Instance"/> getter <see cref="MethodInfo"/>
/// if the resolved method is an instance method on an <see cref="AbstractOptionGroup"/>; otherwise, <see langword="null"/>.
/// </param>
/// <param name="notFound">When this method returns, contains a flag that indicates if the member was not found, as null can be returned from other circumstances too.</param>
/// <returns>The resolved <see cref="MethodInfo"/> if found; otherwise, <see langword="null"/>.</returns>
protected MethodInfo? ResolveMethod(AbstractOptionGroup group, PropertyInfo property, out Type type, out MethodInfo? instanceGetter, out bool notFound)
protected MethodInfo? ResolveMethod(AbstractOptionGroup group, PropertyInfo property, out Type type, out MethodInfo? instanceGetter)
{
return ResolveMember(group, property, out type, out instanceGetter, out notFound) as MethodInfo;
return ResolveMember(group, property, out type, out instanceGetter) as MethodInfo;
}
/// <summary>
@@ -14,13 +14,8 @@ public sealed class ModdedOptionSetterAttribute(string? methodName = null, Type?
{
internal Delegate? GetSetter(AbstractOptionGroup group, PropertyInfo property, IModdedOption option)
{
if (ResolveMethod(group, property, out var type, out var instanceGetter, out var notFound) is not { } method)
{
if (notFound)
Error($"Method {MemberName} does not exist in {type.FullName}");
if (ResolveMethod(group, property, out var type, out var instanceGetter) is not { } method)
return null;
}
var valueType = option.GetValueType();
@@ -33,13 +28,8 @@ public sealed class ModdedOptionSetterAttribute(string? methodName = null, Type?
internal Func<int, Delegate?>? GetListSetter(AbstractOptionGroup group, PropertyInfo property, Type valueType)
{
if (ResolveMethod(group, property, out var type, out var instanceGetter, out var notFound) is not { } method)
{
if (notFound)
Error($"Method {MemberName} does not exist in {type.FullName}");
if (ResolveMethod(group, property, out var type, out var instanceGetter) is not { } method)
return null;
}
if (!ValidateListSignature(method, valueType, out var hasIndex, valueType, valueType))
return null;
@@ -20,11 +20,9 @@ public sealed class ModdedOptionVisibilityAttribute(string? memberName = null, T
internal Func<bool>? GetVisibility(AbstractOptionGroup group, PropertyInfo property)
{
if (ResolveMember(group, property, out Type type, out var instanceGetter, out var notFound) is not { } member)
if (ResolveMember(group, property, out Type type, out var instanceGetter) is not { } member)
{
if (notFound)
Error($"Member {MemberName} does not exist in {type.FullName}");
Error($"Member {MemberName} does not exist in {type.FullName}");
return null;
}
@@ -109,11 +107,9 @@ public sealed class ModdedOptionVisibilityAttribute(string? memberName = null, T
internal Func<int, Delegate?>? GetListVisibility(AbstractOptionGroup group, PropertyInfo property)
{
if (ResolveMember(group, property, out Type type, out var instanceGetter, out var notFound) is not { } member)
if (ResolveMember(group, property, out Type type, out var instanceGetter) is not { } member)
{
if (notFound)
Error($"Member {MemberName} does not exist in {type.FullName}");
Error($"Member {MemberName} does not exist in {type.FullName}");
return null;
}
@@ -1,15 +0,0 @@
using System;
namespace MiraAPI.GameOptions.Attributes;
/// <summary>
/// An attribute used to mark a method or property as one that returns an instance of the class it's declared in.
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
public sealed class InstanceGetterAttribute : Attribute;
/// <summary>
/// An attribute used to mark a class as one whose reflection search should include private members.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class SearchPrivateAttribute : Attribute;
File renamed without changes.
+11 -11
View File
@@ -1,14 +1,14 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="MiraApi.TopRightButtonScaleFactor">Échelle de tailles de boutons</string>
<string name="MiraApi.WikiOnBottomRow">Bouton pour le Wiki sous l'interface principale</string>
<string name="Roles">Rôles</string>
<string name="Modifier">Modificateur</string>
<string name="Modifiers">Modificateurs</string>
<string name="MiraApi.RoleTeam.Crewmate">Coéquipier</string>
<string name="MiraApi.RoleTeam.Crewmate.Short">Équipage</string>
<string name="MiraApi.RoleTeam.Impostor">Imposteur</string>
<string name="MiraApi.RoleTeam.Impostor.Short">Impo</string>
<string name="MiraApi.RoleTeam.Neutral">Neutre</string>
<string name="MiraApi.RoleTeam.Neutral.Short">Neutre</string>
<string name="MiraApi.TopRightButtonScaleFactor">Échelle de tailles de boutons</string>
<string name="MiraApi.WikiOnBottomRow">Bouton pour le Wiki sous l'interface principale</string>
<string name="Roles">Rôles</string>
<string name="Modifier">Modificateur</string>
<string name="Modifiers">Modificateurs</string>
<string name="MiraApi.RoleTeam.Crewmate">Coéquipier</string>
<string name="MiraApi.RoleTeam.Crewmate.Short">Équipage</string>
<string name="MiraApi.RoleTeam.Impostor">Imposteur</string>
<string name="MiraApi.RoleTeam.Impostor.Short">Impo</string>
<string name="MiraApi.RoleTeam.Neutral">Neutre</string>
<string name="MiraApi.RoleTeam.Neutral.Short">Neutre</string>
</resources>
+40 -1
View File
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="MiraApi.TopRightButtonScaleFactor">Skala Przycisków w Prawym Górnym</string>
<string name="MiraApi.WikiOnBottomRow">Pokaż Wiki w Dolnym Rzędzie</string>
<string name="MiraApi.WikiOnBottomRow">Pokaż Przycisk w Dolnym Rzędzie</string>
<string name="Roles">Role</string>
<string name="Modifier">Modyfikator</string>
<string name="Modifiers">Modyfikatory</string>
@@ -40,4 +40,43 @@ Przeżyj przez wymagany czas, albo zabij chowających.</string>
<string name="MiraApi.RoleTeam.Impostor.Group">Role Intruzów</string>
<string name="MiraApi.RoleTeam.Neutral.Group">Role Neutralne</string>
<string name="MiraApi.RoleTeam.Other">Inne</string>
<string name="MiraApi.MatchInfoGuide">Informacje O Meczu</string>
<string name="MiraApi.WikiTabPosition.LeftSide">Po Lewo</string>
<string name="MiraApi.WikiTabPosition.RightSide">Po Prawo</string>
<string name="MiraApi.WikiTabPosition.Below">Poniżej UI</string>
<string name="MiraApi.Gamemode">Tryb Gry</string>
<string name="MiraApi.MatchInfoGuideScaleFactor">Skala Menu Z Informacjami O Meczu</string>
<string name="MiraApi.WikiTabPosition">Położenie Przycisków Informacji O Meczu</string>
<string name="MiraApi.ModifierDisplay.Page">Strona</string>
<string name="MiraApi.Page">Strona</string>
<string name="MiraApi.Main">Główne</string>
<string name="MiraApi.AbilityType.Basic">Umiejętność</string>
<string name="MiraApi.AbilityType.Indirect">Umiejętność Pośrednia</string>
<string name="MiraApi.AbilityType.Interaction">Umiejętność Interakcyjna</string>
<string name="MiraApi.AbilityType.Radius">Umiejętność z Zasięgiem</string>
<string name="MiraApi.AbilityType.Menu">Umiejętność z Menu</string>
<string name="MiraApi.AbilityType.Meeting">Umiejętność na Spotkaniu</string>
<string name="MiraApi.AbilityType.SelectiveMeeting">Umiejętność na Spotkaniu z Wyborem</string>
<string name="MiraApi.AbilityType.MeetingMenu">Umiejętność z Menu na Spotkaniu</string>
<string name="Options">Opcję</string>
<string name="MiraApi.Wiki.PlayersTab">Lista Graczy</string>
<string name="MiraApi.Wiki.SettingsTab">Ustawienia Gry</string>
<string name="MiraApi.Wiki.SearchPlaceholder">Wyszukaj...</string>
<string name="MiraApi.Wiki.FilterLabel">Filtruj</string>
<string name="MiraApi.Wiki.OrderLabel">Kolejność</string>
<string name="MiraApi.Wiki.GroupingLabel">Grupuj</string>
<string name="MiraApi.Wiki.VanillaSettings">Vanilla</string>
<string name="MiraApi.Wiki.SearchResults">Wyniki Wyszukiwania</string>
<string name="MiraApi.Wiki.PreviousPage">Poprzednia</string>
<string name="MiraApi.Wiki.NextPage">Następna</string>
<string name="MiraApi.Wiki.NoResultsFound">Brak Wyników</string>
<string name="On">Wł</string>
<string name="Off">Wył</string>
<string name="Enabled">Włączone</string>
<string name="Disabled">Wyłączone</string>
<string name="Active">Aktywne</string>
<string name="Inactive">Nieaktywne</string>
<string name="Activated">Aktywowane</string>
<string name="Deactivated">Dezaktywowane</string>
<string name="MiraApi.EnableVariableColors">Włącz Kolory Zmienne</string>
</resources>
+11 -11
View File
@@ -1,14 +1,14 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="MiraApi.TopRightButtonScaleFactor">Множитель разрешения верх.-правого интерфейса</string>
<string name="MiraApi.WikiOnBottomRow">Кнопка вики под основным интерфейсом</string>
<string name="Roles">Роли</string>
<string name="Modifier">Атрибут</string>
<string name="Modifiers">Атрибуты</string>
<string name="MiraApi.RoleTeam.Crewmate">Член Экипажа</string>
<string name="MiraApi.RoleTeam.Crewmate.Short">Экипаж</string>
<string name="MiraApi.RoleTeam.Impostor">Предатель</string>
<string name="MiraApi.RoleTeam.Impostor.Short">Пред</string>
<string name="MiraApi.RoleTeam.Neutral">Нейтрал</string>
<string name="MiraApi.RoleTeam.Neutral.Short">Нейт</string>
<string name="MiraApi.TopRightButtonScaleFactor">Множитель разрешения верх.-правого интерфейса</string>
<string name="MiraApi.WikiOnBottomRow">Кнопка вики под основным интерфейсом</string>
<string name="Roles">Роли</string>
<string name="Modifier">Атрибут</string>
<string name="Modifiers">Атрибуты</string>
<string name="MiraApi.RoleTeam.Crewmate">Член Экипажа</string>
<string name="MiraApi.RoleTeam.Crewmate.Short">Экипаж</string>
<string name="MiraApi.RoleTeam.Impostor">Предатель</string>
<string name="MiraApi.RoleTeam.Impostor.Short">Пред</string>
<string name="MiraApi.RoleTeam.Neutral">Нейтрал</string>
<string name="MiraApi.RoleTeam.Neutral.Short">Нейт</string>
</resources>