[Localization] Add the resx file for localization and move errors and warnings (#14703)
* Add the resx file for localization and move error and warning strings * Change NStrings.resx -> Errors.resx * using the new namespace Co-authored-by: TJ Lambert <tjlambert@microsoft.com>
This commit is contained in:
Родитель
8b8cf07182
Коммит
1d4daf2b4a
|
@ -0,0 +1,159 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.MaciOS.Nnyeah {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// This class was generated by MSBuild using the GenerateResource task.
|
||||
/// To add or remove a member, edit your .resx file then rerun MSBuild.
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Build.Tasks.StronglyTypedResourceBuilder", "15.1.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Errors {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Errors() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.MaciOS.Nnyeah.Errors", typeof(Errors).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Input file '{0}' doesn't exist..
|
||||
/// </summary>
|
||||
internal static string E0001 {
|
||||
get {
|
||||
return ResourceManager.GetString("E0001", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Output file '{0}' already exists. Use '--force-overwrite' if you want to overwrite it..
|
||||
/// </summary>
|
||||
internal static string E0002 {
|
||||
get {
|
||||
return ResourceManager.GetString("E0002", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unable to read module from file {0}: {1}..
|
||||
/// </summary>
|
||||
internal static string E0003 {
|
||||
get {
|
||||
return ResourceManager.GetString("E0003", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unable to generate output file, unexpected exception: {0}..
|
||||
/// </summary>
|
||||
internal static string E0004 {
|
||||
get {
|
||||
return ResourceManager.GetString("E0004", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Module is not loaded. Call Load first..
|
||||
/// </summary>
|
||||
internal static string E0005 {
|
||||
get {
|
||||
return ResourceManager.GetString("E0005", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to IConvertible interfaces are not supported yet. If this code gets called, it will fail. Consider contacting the library maintainer to request a dotnet 6 upgrade..
|
||||
/// </summary>
|
||||
internal static string N0001 {
|
||||
get {
|
||||
return ResourceManager.GetString("N0001", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to CopyArray for nuint is not supported yet. If this method is called, it will not function correctly..
|
||||
/// </summary>
|
||||
internal static string N0002 {
|
||||
get {
|
||||
return ResourceManager.GetString("N0002", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Package does not need changes - no output generated..
|
||||
/// </summary>
|
||||
internal static string N0003 {
|
||||
get {
|
||||
return ResourceManager.GetString("N0003", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to In {0}.{1}, found reference to {2}. Added {3} IL instructions and removed {4} IL instructions..
|
||||
/// </summary>
|
||||
internal static string N0004 {
|
||||
get {
|
||||
return ResourceManager.GetString("N0004", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to In {0}.{1}, found reference to {2}. Added {3} IL instructions..
|
||||
/// </summary>
|
||||
internal static string N0005 {
|
||||
get {
|
||||
return ResourceManager.GetString("N0005", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to In {0}.{1}, found reference to {2} - this is not transformable and will likely not work if invoked..
|
||||
/// </summary>
|
||||
internal static string N0006 {
|
||||
get {
|
||||
return ResourceManager.GetString("N0006", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
|
||||
<data name="N0001" xml:space="preserve">
|
||||
<value>IConvertible interfaces are not supported yet. If this code gets called, it will fail. Consider contacting the library maintainer to request a dotnet 6 upgrade.</value>
|
||||
</data>
|
||||
|
||||
<data name="N0002" xml:space="preserve">
|
||||
<value>CopyArray for nuint is not supported yet. If this method is called, it will not function correctly.</value>
|
||||
</data>
|
||||
|
||||
<data name="N0003" xml:space="preserve">
|
||||
<value>Package does not need changes - no output generated.</value>
|
||||
</data>
|
||||
|
||||
<data name="N0004" xml:space="preserve">
|
||||
<value>In {0}.{1}, found reference to {2}. Added {3} IL instructions and removed {4} IL instructions.</value>
|
||||
</data>
|
||||
|
||||
<data name="N0005" xml:space="preserve">
|
||||
<value>In {0}.{1}, found reference to {2}. Added {3} IL instructions.</value>
|
||||
</data>
|
||||
|
||||
<data name="N0006" xml:space="preserve">
|
||||
<value>In {0}.{1}, found reference to {2} - this is not transformable and will likely not work if invoked.</value>
|
||||
</data>
|
||||
|
||||
<data name="E0001" xml:space="preserve">
|
||||
<value>Input file '{0}' doesn't exist.</value>
|
||||
</data>
|
||||
|
||||
<data name="E0002" xml:space="preserve">
|
||||
<value>Output file '{0}' already exists. Use '--force-overwrite' if you want to overwrite it.</value>
|
||||
</data>
|
||||
|
||||
<data name="E0003" xml:space="preserve">
|
||||
<value>Unable to read module from file {0}: {1}.</value>
|
||||
</data>
|
||||
|
||||
<data name="E0004" xml:space="preserve">
|
||||
<value>Unable to generate output file, unexpected exception: {0}.</value>
|
||||
</data>
|
||||
|
||||
<data name="E0005" xml:space="preserve">
|
||||
<value>Module is not loaded. Call Load first.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -9,8 +9,6 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
public class MethodTransformations {
|
||||
static List<Transformation>? allTransforms;
|
||||
static Dictionary<string, Transformation>? transformTable;
|
||||
const string ConvertibleMessage = "IConvertible interfaces are not supported yet. If this code gets called, it will fail. Consider contacting the library maintainer to request a dotnet 6 upgrade.";
|
||||
const string CopyArrayMessage = "CopyArray for nuint is not supported yet. If this method is called, it will not function correctly.";
|
||||
|
||||
public Dictionary<string, Transformation> GetTransforms (ModuleDefinition module, Func<List<bool>, CustomAttribute> attrBuilder)
|
||||
{
|
||||
|
@ -596,21 +594,21 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
"System.Void System.nint::.cctor()"
|
||||
),
|
||||
|
||||
new Transformation ("System.Boolean System.nint::System.IConvertible.ToBoolean(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Byte System.nint::System.IConvertible.ToByte(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Char System.nint::System.IConvertible.ToChar(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.DateTime System.nint::System.IConvertible.ToDateTime(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Decimal System.nint::System.IConvertible.ToDecimal(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Double System.nint::System.IConvertible.ToDouble(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Int16 System.nint::System.IConvertible.ToInt16(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Int32 System.nint::System.IConvertible.ToInt32(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Int64 System.nint::System.IConvertible.ToInt64(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.SByte System.nint::System.IConvertible.ToSByte(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Single System.nint::System.IConvertible.ToSingle(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.UInt16 System.nint::System.IConvertible.ToUInt16(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.UInt32 System.nint::System.IConvertible.ToUInt32(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.UInt64 System.nint::System.IConvertible.ToUInt64(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Object System.nint::System.IConvertible.ToType(System.Type,System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Boolean System.nint::System.IConvertible.ToBoolean(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Byte System.nint::System.IConvertible.ToByte(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Char System.nint::System.IConvertible.ToChar(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.DateTime System.nint::System.IConvertible.ToDateTime(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Decimal System.nint::System.IConvertible.ToDecimal(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Double System.nint::System.IConvertible.ToDouble(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Int16 System.nint::System.IConvertible.ToInt16(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Int32 System.nint::System.IConvertible.ToInt32(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Int64 System.nint::System.IConvertible.ToInt64(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.SByte System.nint::System.IConvertible.ToSByte(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Single System.nint::System.IConvertible.ToSingle(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.UInt16 System.nint::System.IConvertible.ToUInt16(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.UInt32 System.nint::System.IConvertible.ToUInt32(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.UInt64 System.nint::System.IConvertible.ToUInt64(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Object System.nint::System.IConvertible.ToType(System.Type,System.IFormatProvider)", Errors.N0001),
|
||||
|
||||
// nuint
|
||||
new Transformation(
|
||||
|
@ -832,21 +830,21 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
"System.Void System.nuint::.cctor()"
|
||||
),
|
||||
|
||||
new Transformation ("System.Boolean System.nuint::System.IConvertible.ToBoolean(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Byte System.nuint::System.IConvertible.ToByte(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Char System.nuint::System.IConvertible.ToChar(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.DateTime System.nuint::System.IConvertible.ToDateTime(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Decimal System.nuint::System.IConvertible.ToDecimal(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Double System.nuint::System.IConvertible.ToDouble(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Int16 System.nuint::System.IConvertible.ToInt16(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Int32 System.nuint::System.IConvertible.ToInt32(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Int64 System.nuint::System.IConvertible.ToInt64(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.SByte System.nuint::System.IConvertible.ToSByte(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Single System.nuint::System.IConvertible.ToSingle(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.UInt16 System.nuint::System.IConvertible.ToUInt16(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.UInt32 System.nuint::System.IConvertible.ToUInt32(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.UInt64 System.nuint::System.IConvertible.ToUInt64(System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Object System.nuint::System.IConvertible.ToType(System.Type,System.IFormatProvider)", ConvertibleMessage),
|
||||
new Transformation ("System.Boolean System.nuint::System.IConvertible.ToBoolean(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Byte System.nuint::System.IConvertible.ToByte(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Char System.nuint::System.IConvertible.ToChar(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.DateTime System.nuint::System.IConvertible.ToDateTime(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Decimal System.nuint::System.IConvertible.ToDecimal(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Double System.nuint::System.IConvertible.ToDouble(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Int16 System.nuint::System.IConvertible.ToInt16(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Int32 System.nuint::System.IConvertible.ToInt32(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Int64 System.nuint::System.IConvertible.ToInt64(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.SByte System.nuint::System.IConvertible.ToSByte(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Single System.nuint::System.IConvertible.ToSingle(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.UInt16 System.nuint::System.IConvertible.ToUInt16(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.UInt32 System.nuint::System.IConvertible.ToUInt32(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.UInt64 System.nuint::System.IConvertible.ToUInt64(System.IFormatProvider)", Errors.N0001),
|
||||
new Transformation ("System.Object System.nuint::System.IConvertible.ToType(System.Type,System.IFormatProvider)", Errors.N0001),
|
||||
|
||||
// why warnings for this?
|
||||
// Because in .NET 6 there is no direct equivalent of this call.
|
||||
|
@ -855,9 +853,9 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
// Not doing this right now since a survey of nuget.org shows that these methods
|
||||
// are never called in the wild.
|
||||
new Transformation ("System.Void System.nuint::CopyArray(System.IntPtr,System.nuint[],System.Int32,System.Int32)",
|
||||
CopyArrayMessage),
|
||||
Errors.N0002),
|
||||
new Transformation ("System.Void System.nuint::CopyArray(System.nuint[],System.Int32,System.IntPtr,System.Int32)",
|
||||
CopyArrayMessage),
|
||||
Errors.N0002),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,12 +40,12 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
}
|
||||
|
||||
if (!File.Exists (infile)) {
|
||||
Console.Error.WriteLine ($"input file '{infile}' doesn't exist.");
|
||||
Console.Error.WriteLine (Errors.E0001, infile);
|
||||
Environment.Exit (1);
|
||||
}
|
||||
|
||||
if (File.Exists (outfile) && !forceOverwrite) {
|
||||
Console.Error.WriteLine ($"output file '{outfile}' already exists. Use '--force-overwrite' if you want to overwrite it.");
|
||||
Console.Error.WriteLine (Errors.E0002, outfile);
|
||||
Environment.Exit (1);
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
try {
|
||||
reworker.Load ();
|
||||
} catch (Exception e) {
|
||||
Console.Error.WriteLine ($"Unable to read module from file {infile}: {e.Message}.");
|
||||
Console.Error.WriteLine (Errors.E0003, infile, e.Message);
|
||||
Environment.Exit (1);
|
||||
}
|
||||
|
||||
|
@ -74,12 +74,12 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
warnings.ForEach (Console.WriteLine);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Console.Error.Write ($"Unable to generate output file, unexpected exception: {e.Message}");
|
||||
Console.Error.Write (Errors.E0004, e.Message);
|
||||
Environment.Exit (1);
|
||||
}
|
||||
} else {
|
||||
if (verbose) {
|
||||
Console.WriteLine ("Package does not need changes - no output generated.");
|
||||
Console.WriteLine (Errors.N0003);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
void CheckModule ()
|
||||
{
|
||||
if (module == EmptyModule)
|
||||
throw new Exception ("Module is not loaded. Call Load first.");
|
||||
throw new Exception (Errors.E0005);
|
||||
}
|
||||
|
||||
public void Rework (Stream stm)
|
||||
|
|
|
@ -17,12 +17,10 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
|
||||
public override string HelpfulMessage ()
|
||||
{
|
||||
var sb = new StringBuilder ();
|
||||
sb.Append ($"In {ContainerName}.{MethodName}, found reference to {TargetOperand}. Added {AddedCount} IL instructions");
|
||||
if (RemovedCount > 0)
|
||||
sb.Append ($" and removed {RemovedCount} IL instructions");
|
||||
sb.Append ('.');
|
||||
return sb.ToString ();
|
||||
return string.Format (Errors.N0004, ContainerName, MethodName, TargetOperand, AddedCount, RemovedCount);
|
||||
|
||||
return string.Format (Errors.N0005, ContainerName, MethodName, TargetOperand, AddedCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Microsoft.MaciOS.Nnyeah {
|
|||
|
||||
public override string HelpfulMessage ()
|
||||
{
|
||||
return $"In {ContainerName}.{MethodName}, found reference to {TargetOperand} - this is not transformable and will likely not work if invoked.";
|
||||
return string.Format (Errors.N0006, ContainerName, MethodName, TargetOperand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,4 +14,15 @@
|
|||
<PackageReference Include="Mono.Cecil" Version="0.11.4" />
|
||||
<PackageReference Include="Mono.Options" Version="6.12.0.148" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Errors.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Errors.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Errors.Designer.cs">
|
||||
<DependentUpon>Errors.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
Загрузка…
Ссылка в новой задаче