Question

Je veux passer outre une chaîne à partir d'un System.ComponentModel.DataAnnotations pour un projet ASP.NET. Est-ce que je dois faire un ensemble de satellites, de jouer avec les tâches de construction personnalisées, al.exe etc.? Même si oui, je ne pouvais pas trouver comment convertir .resx à .resources pour nourrir à al.exe. Et si non, où mettre le .resx. et comment le nommer?

UPD: Pour faire clair: je voulais utiliser une chaîne de ressource personnalisée au lieu d'un à partir de la ressource par défaut de l'ensemble. Je ne voulais pas faire des changements dans la tout lieu qui utilise cette chaîne. Après tout, les ressources existent pour eux primordial.

Était-ce utile?

La solution 2

Bien que cela est étrange, surtout pour les personnes familières avec les technologies de localisation open source, on ne peut pas construire un ensemble de satellites pour tout ensemble du système ou même un 3e parti signé un:

  

Si votre assemblage principal utilise fort   nommage, les ensembles de satellites doivent être   signé avec la même clé privée   l'ensemble principal. Si la   clé publique / privée paire ne correspond pas à   entre le principal et le satellite   ensembles, vos ressources ne seront pas   chargé.

Que la même chose est possible automatiquement, mais sans un ensemble de satellites, est inconnue, bien que je doute.

Autres conseils

Phil Haack a un excellent article activités locales ASP.Net MVC validation qui guide spécifiquement vous par vos cordes impérieuses. Cet article applique plus à DataAnnotations que Finalité ASP.net MVC . Alors, cela vous aidera cependant que vous utilisez DataAnnotattions .

Ci-dessous j'ai énuméré les étapes les plus simples pour ajouter des ressources Localisés dans Visual Studio.

  1. Ouvrez le Project Properties dialogue.
  2. Sélectionnez Resources onglet.
  3. Cliquez pour créer une nouvelle valeur par défaut fichier de ressources .
  4. Cela va créer deux fichiers dans votre dossier Properties.
    • Resources.resx
    • Resources.Designer.cs
  5. Lorsque Resources.resx a ouvert, changez-est Access Modifier Public .
  6. Ajoutez vos chaînes.

Pour ajouter supplémentaires fichiers de ressources pour cultures spécifiques vous devrez.

  1. Faites un clic droit de votre Project dans la Solution Explorer .
  2. Sélectionnez Ajouter -> Nouvel élément -> Ressources Fichier.
  3. Name it Resources.en-us.resx . (Remplacer « en-nous » avec approprié code)
  4. Cliquez sur Ajouter
  5. Faites-le glisser dans le dossier Properties.
  6. Ouvrir Resources.en-us.resx et changez-est Access Modifier Public .
  7. Ajoutez vos chaînes.
  8. Répétez l'opération pour chaque culture, il faut soutien.

Lors de la construction VS convertira les .resx .resource fichiers et construire des classes wrapper pour vous. Vous pouvez alors accéder via l'espace de noms YourAssembly.Properties.Resources .

Avec cette instruction à l'aide.

using YourAssembly.Properties;

Vous pouvez décorer avec des attributs comme ceci:

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

Note: je Propriétés dossier de cohérence. Pour utiliser les App_GlobalResources déplacer vos .resx fichiers là et changer d'instruction à l'aide de faire correspondre le nom du répertoire. Comme ceci:

using YourAssembly.App_GlobalResources;

Edit: Le plus proche que vous pouvez obtenir à fortement typées noms de ressources serait de faire quelque chose comme ceci:

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

Vous pouvez ensuite décorer avec des attributs comme celui-ci.

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

Pour activer la détection de la culture du client automatique ajouter le globalizationsection dans le fichier web.config .

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

Ici, j'ai permis une culture client et définir le culture et uiculture " auto " avec un défaut de « fr-fr ».


Création séparées assemblées par satellite:

Le MSDN Création d'assemblages satellites article vous aidera aussi. Si vous êtes nouveau à des ensembles satellites assurez-vous que vous lisez Emballage et des ressources Déploiement .

Lors de la création des bibliothèques satellites dans le passé, je l'ai trouvé utile d'utiliser VS construire des événements. Ce sont les étapes que je prendrais.

  1. Créer une directive Class Library projet dans ma solution.
  2. Créer ou ajouter mon .resx fichiers à ce projet.
  3. Ajoutez Post-Build Event Project Properties dialogue. (Comme celui ci-dessous)

Exemple VS Post-script de construction:

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

Si vous préférez ne pas utiliser Resgen.exe pour convertirvotre .resx fichiers, vous pouvez faire quelque chose comme ça.

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();
            }
        }
    }
}

L'un des Peignent potentiels dos à faire la conversion de cette façon est la nécessité de faire référence à la System.Windows.Forms.dll. Vous aurez toujours besoin d'utiliser Assembly Linker .

Edit: Comme WRAR nous a rappelé, si vous signez vos assemblées clés doit correspondre .

En supposant que vous voulez remplacer les chaînes de message d'erreur par défaut dans la validation des attributs, vous pouvez le faire en réglant le ErrorMessageResourceName et les propriétés de ErrorMessageResourceType comme ceci:

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

Vous pouvez créer un fichier de ressources appelé MyResourceFile.resx qui contient Required_Username avec le message d'erreur que vous voulez.

Hope this helps.

Si le serveur ne dispose pas de modules linguistiques .NET installés, peu importe ce que CurrentUICulture est réglé sur, vous aurez toujours l'anglais dans les messages de validation de DataAnnotations. Ce hack épique fonctionne pour nous.

  • Aller à la page de téléchargement "Microsoft .NET Framework 4.6.1 Language Pack" https://www.microsoft.com/en-us/download/details.aspx?id=49977
  • Sélectionner la langue et télécharger
  • Extrait NDP461-KB3102436-x86-x64-AllOS- {} LANG .exe avec 7-Zip
  • Extraire le fichier CAB x64-Windows10.0-KB3102502-x64.cab avec 7-Zip
  • Recherchez "msil_system.componentmod..notations.resources _...."
  • ... où vous trouverez "system.componentmodel.dataannotations.resources.dll"
  • Ouvrir .resources.dll avec ILSpy, recherchez des ressources et cliquez sur le bouton Enregistrer ci-dessus chaîne de table pour enregistrer en tant que System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources. {LANGUE} .resources
  • Ajoutez à votre projet en dire « Ressources »
  • Vérifiez le bon fonctionnement des fichiers Construire propriété Action des ressources fichiers est réglé sur « ressource incorporée »

Ensuite, dans une méthode PreStart de votre projet vous écrasez le System.ComponentModel.DataAnnotations.Resources.DataAnnotationsResources.resourceMan champ statique privé (vous a dit qu'il était un hack) avec ceux que vous avez dans votre projet.

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);
    }
}

Je veux donner une réponse à la même idée que par Duncan Smart mais pour .NET 2.2 de base au lieu de 4.x .NET Framework.

Ici, il est.

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);
    }
}

Et j'appelle cela comme ceci:

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

De plus, je crée un fichier ~/Resources/<YourResource>.resx et peuplé avec les valeurs par défaut et les modifier à volonté. Enfin, je crée une classe publique vide <YourResource>.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top