Domanda

Voglio ignorare una stringa da un System.ComponentModel.DataAnnotations per un progetto ASP.NET. Ho bisogno di fare un assembly satellite, scherzi con compiti di generazione personalizzata, al.exe ecc? Anche se sì, non riuscivo a trovare il modo di convertire .resx a .resources ad alimentarlo a al.exe. E se no, dove mettere la .resx. e come chiamarlo?

UPD: Per chiarire: ho voluto usare una stringa risorsa personalizzata invece di uno dalla risorsa di default dal gruppo. Io non voglio fare cambiamenti nella ogni luogo che utilizza tale stringa. Dopo tutto, le risorse esistono solo per loro l'override.

È stato utile?

Soluzione 2

Anche se questo è strano, soprattutto per le persone che hanno familiarità con le tecnologie di localizzazione open source, non si può costruire un assembly satellite per qualsiasi sistema di montaggio o anche un 3rd-party firmato uno:

  

Se il montaggio principale utilizza forte   denominazione, assembly satellite devono essere   firmato con la stessa chiave privata   dell'assieme principale. Se la   / Privato coppia di chiavi pubblica non corrisponde   tra il principale e satellitare   assemblee, le risorse non saranno   caricato.

Sia che lo stesso è possibile automaticamente, ma senza un assembly satellite, è sconosciuto, anche se dubito che.

Altri suggerimenti

Phil Haack ha un eccellente articolo Localizzazione di ASP.Net MVC convalida , che guida l'utente in particolare attraverso l'override le corde. Questo articolo si applica di più per DataAnnotations di quanto non faccia ASP.net MVC . Quindi, ciò contribuirà tuttavia si sta usando DataAnnotattions .

Qui di seguito ho elencato i passi più semplici per aggiungere le risorse localizzate in Visual Studio.

  1. Aprire il Project Properties finestra di dialogo.
  2. Selezionare il Resources scheda.
  3. Fare clic per creare un nuovo di default file di risorse .
  4. Questo creerà due file nella cartella Properties.
    • Resources.resx
    • Resources.Designer.cs
  5. Quando Resources.resx ha aperto, cambiare è Access Modifier per Public .
  6. Aggiungi tue corde.

Per aggiungere ulteriori file di risorse per culture specifiche si avrà bisogno di.

  1. Fare clic destro il tuo Project nella Solution Explorer .
  2. Seleziona Aggiungi -> New Item -> Resource File.
  3. Nome Resources.en-us.resx . (Sostituire 'it-it' con adeguate codice)
  4. Fare clic su Aggiungi
  5. trascinarlo nella cartella Properties.
  6. Apri Resources.en-us.resx e cambiare è Access Modifier per Public .
  7. Aggiungi tue corde.
  8. Ripeti per ogni cultura è necessario supporto.

Durante la compilazione VS convertirà i .resx i file in file .resource e costruire classi wrapper per voi. È quindi possibile accedere tramite il namespace YourAssembly.Properties.Resources .

Con questa istruzione using.

using YourAssembly.Properties;

Potete decorare con attributi come questo:

[Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "MyStringName")]

Nota: Ho usato il Proprietà cartella per coerenza. Per utilizzare le App_GlobalResources muovere le .resx file lì e cambiare la vostra istruzione using per abbinare il nome della directory. In questo modo:

using YourAssembly.App_GlobalResources;

Modifica: Il più vicino che si può arrivare a tipizzato fortemente i nomi di risorsa potrebbe essere quella di fare qualcosa di simile:

public class ResourceNames
{
    public const string EmailRequired = "EmailRequired";
}

È quindi possibile decorare con attributi come questo.

[Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = ResourceNames.EmailRequired)]

Per attivare il rilevamento automatico di cultura client aggiungere il globalizationsection per il file web.config .

<configuration>
    <system.web>
        <globalization enableClientBasedCulture="true" culture="auto:en-us" uiCulture="auto:en-us"/>
    </system.web>
<configuration>

Qui ho permesso a una cultura cliente basato e impostare il cultura e uiculture per " auto " il valore predefinito è " it-it ".


La creazione di assembly satellite separati:

Assembly satellite

Il MSDN Creazione articolo vi aiuterà pure. Se sei un nuovo assembly satellite assicuratevi di leggere imballaggio e la distribuzione delle risorse .

Durante la creazione di assembly satellite in passato, ho trovato utile usare VS costruire eventi. Questi sono i passi che avrebbe preso.

  1. Crea un separato Class Library progetto nella mia soluzione.
  2. Crea o Aggiungere la mia .resx file a questo progetto.
  3. Aggiungi un Post-Build Event per la finestra di Project Properties . (Come quella qui sotto)

Esempio VS post-generazione Script:

set RESGEN="C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\resgen.exe"
set LINKER="C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\al.exe"
set ASSEMBLY=$(TargetName)
set SOURCEDIR=$(ProjectDir)
Set OUTDIR=$(TargetDir)

REM Build Default Culture Resources (en)
%RESGEN% %SOURCEDIR%en\%ASSEMBLY%.en.resx  %SOURCEDIR%en\%ASSEMBLY%.resources

REM Embed Default Culture
%LINKER% /t:lib /embed:%SOURCEDIR%en\%ASSEMBLY%.resources /culture:en /out:%OUTDIR%%ASSEMBLY%.resources.dll
REM Embed English Culture
IF NOT EXIST %OUTDIR%en\ MKDIR $%OUTDIR%en\
%LINKER% /t:lib /embed:%SOURCEDIR%en\%ASSEMBLY%.resources /culture:en /out:%OUTDIR%en\%ASSEMBLY%.resources.dll


REM These are just a byproduct of using the project build event to run the resource build script
IF EXIST %OUTDIR%%ASSEMBLY%.dll DEL %OUTDIR%%ASSEMBLY%.dll
IF EXIST %OUTDIR%%ASSEMBLY%.pdb DEL %OUTDIR%%ASSEMBLY%.pdb

Se si preferisce non usare Resgen.exe per convertireil tuo .resx file, si potrebbe fare qualcosa di simile.

using System;
using System.Collections;
using System.IO;
using System.Resources;

namespace ResXConverter
{
    public class ResxToResource
    {
        public void Convert(string resxPath, string resourcePath)
        {
            using (ResXResourceReader resxReader = new ResXResourceReader(resxPath))
            using (IResourceWriter resWriter = new ResourceWriter(
                    new FileStream(resourcePath, FileMode.Create, FileAccess.Write)))
            {
                foreach (DictionaryEntry entry in resxReader)
                {
                    resWriter.AddResource(entry.Key.ToString(), entry.Value);
                }
                resWriter.Generate();
                resWriter.Close();
            }
        }
    }
}

Uno dei potenziali spalle di disegnare a fare la conversione in questo modo è la necessità di fare riferimento al System.Windows.Forms.dll. Sarà comunque necessario usare Assembly Linker .

Edit: Come WRAR ci ha ricordato, se si firma vostre assemblee le chiavi deve corrispondere .

Supponendo che si desidera ignorare le stringhe di messaggio di errore predefinito nella convalida attributi, è possibile farlo impostando la proprietà ErrorMessageResourceName come questo ErrorMessageResourceType e:

[Required(ErrorMessageResourceName = "Required_Username", ErrorMessageResourceType = typeof(MyResourceFile)]
public string Username { get; set; }

È possibile creare un file di risorse chiamato MyResourceFile.resx che contiene Required_Username con il messaggio di errore che si desidera.

Spero che questo aiuti.

Se il server non dispone di pacchetti di lingua .NET installati allora non importa quanto CurrentUICulture è impostato, potrai sempre ottenere l'inglese in messaggi di convalida DataAnnotations. Questo hack epico lavora per noi.

  • Vai a "Microsoft .NET Framework Language Pack 4.6.1" pagina di download https://www.microsoft.com/en-us/download/details.aspx?id=49977
  • Seleziona la lingua e scarica
  • Estrai NDP461-KB3102436-x86-x64-AllOS- {LANG} .exe con 7-Zip
  • Estratto x64-Windows10.0-KB3102502-x64.cab file CAB con 7-Zip
  • Individuare "msil_system.componentmod..notations.resources _...."
  • ... in cui si trovano "system.componentmodel.dataannotations.resources.dll"
  • Apri .resources.dll con ILSpy, individuare le risorse e fare clic sul pulsante Salva sopra tabella di stringhe da salvare come System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources. {LANGUAGE} resources
  • Aggiungi al progetto sotto dire "Risorse"
  • Assicurarsi che i file Anno di costruzione d'azione dei file di risorse è impostato su "Risorsa incorporata"

Poi, in un metodo di pre-partenza del progetto si sovrascrive il campo statico privato System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources.resourceMan (detto che era un hack) con quelli che avete nel vostro progetto.

using System;
using System.Linq;
using System.Reflection;
using System.Resources;

[assembly: WebActivator.PreApplicationStartMethod(typeof(ResourceManagerUtil), nameof(ResourceManagerUtil.PreStart))]

class ResourceManagerUtil
{
    public static void PreStart()
    {
        initDataAnnotationsResourceManager();
    }

    /// <summary>
    /// If the server doesn't have .NET language packs installed then no matter what CurrentUICulture is set to, you'll always get English in 
    /// DataAnnotations validation messages. Here we override DataAnnotationsResources to use a ResourceManager that uses language .resources 
    /// files embedded in this assembly.
    /// </summary>
    static void initDataAnnotationsResourceManager()
    {
        var embeddedResourceNamespace = "<YourProjectDefaultNamespace>.<FolderYouSavedResourcesFilesIn>";
        var dataAnnotationsResourcesName = "System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources";
        var thisAssembly = typeof(ResourceManagerUtil).Assembly;
        var dataAnnotationsAssembly = typeof(System.ComponentModel.DataAnnotations.ValidationAttribute).Assembly;

        var resourceManager = new ResourceManager(embeddedResourceNamespace + "." + dataAnnotationsResourcesName, thisAssembly);

        // Set internal field `DataAnnotationsResources.resourceMan`
        var dataAnnotationsResourcesType = dataAnnotationsAssembly.GetType(dataAnnotationsResourcesName);
        var resmanProp = dataAnnotationsResourcesType.GetField("resourceMan", BindingFlags.NonPublic | BindingFlags.Static);
        resmanProp.SetValue(null, resourceManager);
    }
}

Voglio dare una risposta con la stessa idea da Duncan intelligente, ma per .NET 2.2 core invece di 4.x .NET Framework.

Ecco qui.

using System;
using System.Linq;
using System.Reflection;
using System.Resources;

public static class ResourceManagerHack
{
    /// <summary>
    /// If the server doesn't have .NET language packs installed then no matter what CurrentUICulture is set to, you'll always get English in 
    /// DataAnnotations validation messages. Here we override DataAnnotationsResources to use a ResourceManager that uses language .resources 
    /// files embedded in this assembly.
    /// </summary>
    public static void OverrideComponentModelAnnotationsResourceManager()
    {
        EnsureAssemblyIsLoaded();

        FieldInfo resourceManagerFieldInfo = GetResourceManagerFieldInfo();
        ResourceManager resourceManager = GetNewResourceManager();
        resourceManagerFieldInfo.SetValue(null, resourceManager);
    }

    private static FieldInfo GetResourceManagerFieldInfo()
    {
        var srAssembly = AppDomain.CurrentDomain
                                  .GetAssemblies()
                                  .First(assembly => assembly.FullName.StartsWith("System.ComponentModel.Annotations,"));
        var srType = srAssembly.GetType("System.SR");
        return srType.GetField("s_resourceManager", BindingFlags.Static | BindingFlags.NonPublic);
    }
    internal static ResourceManager GetNewResourceManager()
    {
        return new ResourceManager($"{typeof(<YourResource>).Namespace}.Strings", typeof(<YourResource>).Assembly);
    }
    private static void EnsureAssemblyIsLoaded()
    {
        var _ = typeof(System.ComponentModel.DataAnnotations.RequiredAttribute);
    }
}

E io chiamo questo modo:

public static void Main(string[] args)
{
    ResourceManagerHack.OverrideComponentModelAnnotationsResourceManager();
    CreateWebHostBuilder(args).Build().Run();
}

Inoltre, ho creato un file ~/Resources/<YourResource>.resx e popolata con i valori di default e li cambiato a piacimento. Infine ho creato una <YourResource> pubblico classe vuota.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top