none
Localisation RRS feed

  • Question

  • Bonjour

    je monte un site en 3 langues.

    pour tous ce qui est textes menus et autre (gestions des profiles) pas de soucis, j'utilise les ressources mais là ou ça se gate c'est pour les bases de données j'ai opté pour un champs par langue exemple LibelleFR, LibelleGB, LibelleES.

    avez vous déjà utilisé cette technique pour éclairer ma lanterne.

    merci

    samedi 9 septembre 2006 11:49

Toutes les réponses

  • Bonsoir,

    Pour ma part, je gère l'ensemble des ressources en base de données. J'ai donc réimplémenté un ResourceManager, ResourceSet et ResourceReader ... Le tout monter en cache à la demande.
    Ma base à donc un modèle avec une table contenant les champs : key, neutral, fr, en, ...

    --
    arno -
    http://www.dotnetguru2.org/acleret/

    dimanche 17 septembre 2006 08:33
  • Bonjour,

    Pour ma part, je gère l'ensemble des ressources en base de données. J'ai donc réimplémenté un ResourceManager, ResourceSet et ResourceReader ... Le tout monter en cache à la demande.
    Ma base à donc un modèle avec une table contenant les champs : key, neutral, fr, en, ...

    --
    arno -
    http://www.dotnetguru2.org/acleret/

    dimanche 17 septembre 2006 08:34
  • bonjour Arnaud

    pourriez vous etre plus explicif ?
    une page de lien ferait l'affaire pour voir la base et voir le fonctionnement, car moi aussi j'ai fait comme l'interlocuteur ayant lancé le sujet.

    une autre approche plus "dot.net" serait la bien venue non ?

    mercredi 11 octobre 2006 14:09
  • Bonjour,

    Le principe est le suivant (exemple de code en .Net 1.1) :

    1 - Ecrire une classe "DbResourceManager" dérivant de "ResourceManager" :

    public class DbResourceManager : ResourceManager
    {
        private string connectionString;
     
        public DbResourceManager(string connectionString)
        {
             this.connectionString = connectionString;
             base.ResourceSets = new Hashtable(CaseInsensitiveHashCodeProvider.Default,CaseInsensitiveComparer.Default );
        }

        protected override ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
        {
             if(!ResourceSets.Contains(culture.Name))ResourceSets.Add(culture.Name, new DbResourceSet(connectionString, culture));
             return ResourceSets[culture.Name] as DbResourceSet;
        }
    }

    2 - Ecrire une classe "DbResourceSet" dérivant de "ResourceSet" :

    public class DbResourceSet : ResourceSet
    {
        public DbResourceSet(string connectionString, CultureInfo culture): base(new DbResourceReader(connectionString,culture)){}
       
        public override Type GetDefaultReader(){return typeof(DbResourceReader);}
      
        public override string GetString(string name, bool ignoreCase)
        {
             return base.GetString(name,ignoreCase);
        }
      
        public override string GetString(string name)
        {
             return base.GetString(name); 
        }
    }

    3 - Ecrire une classe "DbResourceReader" implémentant "IResourceReader" :

    public class DbResourceReader : IResourceReader
    {
         private string connectionString;
         private string cultureName;

         public DbResourceReader(string connectionString,CultureInfo culture)
         {
              this.connectionString = connectionString;
              this.cultureName = culture.Name;
         }

         IEnumerator IEnumerable.GetEnumerator(){return this.GetEnumerator();}

         public IDictionaryEnumerator GetEnumerator()
        {
            if(cultureName == string.Empty)cultureName = "Neutral";
            Hashtable dictionary = new Hashtable(CaseInsensitiveHashCodeProvider.Default ,CaseInsensitiveComparer.Default );
            SqlConnection connection = SQLProvider.GetConnection(connectionString);
            try
            {
                 SQLProvider.OpenConnection(connection);
                 SqlCommand command = SQLProvider.CreateCommand(connection,CommandType.StoredProcedure,"dbo.GetResourceManager",SQLProvider.CreateParameter("@CultureName",SqlDbType.VarChar,20,ParameterDirection.Input,this.cultureName)); 
                 try
                 {
                       SqlDataReader reader = SQLProvider.ExecuteReader(command);
                       try{while(reader.Read()) if(reader.GetValue(1) != DBNull.Value)dictionary.Add(reader.GetString(0), reader.GetString(1));}
                       finally{SQLProvider.CloseReader(reader,command,true);}
                 }
                 catch{/*ne rien faire*/}
             }
             finally{SQLProvider.CloseConnection(connection);}
             return dictionary.GetEnumerator();
         }

      public void Close(){}

      public void Dispose(){}

    }

    4 - Créer la base de donnée et la tables de stockage des ressources ayant le schéma minimum suivant :

    • KeyName
    • Neutral
    • fr
    • en
    • ...

    5 - Ecrire une procédure stockée d'accès aux données de ressources :

    CREATE PROCEDURE dbo.GetResourceManager

    (

        @CultureName NVARCHAR(20)

    )

    AS

    BEGIN

                    SET NOCOUNT ON

                    DECLARE @SqlString NVARCHAR (100)

                    SET @SqlString = N'SELECT KeyName,[' + @CultureName + N']' + N' FROM dbo.ResourceManager'

                    EXECUTE sp_executesql @SqlString

                    RETURN

    END

    6 - Initialiser les ressources à la demande en créant par exemple une classe de gestion des configurations pouvant inclure le code suivant :

    public class ApplicationSettings
    {
         static ApplicationSettings(){}
         private ApplicationSettings(){}

         public static DbResourceManager ResourceManager
         {
              get
              {
                   try
                   {
                         rwl.AcquireReaderLock(Timeout.Infinite);
                         DbResourceManager resourceManager = (DbResourceManager)CacheManager.Get("ResourceManager");
                         if(resourceManager == null)
                         {
                              rwl.UpgradeToWriterLock(Timeout.Infinite);  
                              resourceManager = (DbResourceManager)CacheManager.Get("ResourceManager");
                              if(resourceManager == null)
                              {
                                   resourceManager = new DbResourceManager(ConnectionStringToDataBase);
                                   CacheManager.Add("ResourceManager",resourceManager); 
                              }
                        }
                        return resourceManager;
                   }  
                   finally
                   {
                       rwl.ReleaseLock();
                   }
              }
         }
    }

    7 - Dans votre code, il vous suffit ensuite d'utiliser l'objet comme suit :

    ApplicationSettings.ResourceManager.GetString("MaRessource") ;

    D'autre surcharge existe permettant de forcer la culture de la ressource à récupérer ...


    Pour info, les classes SQLProvider, CacheManager sont des objets encapsulant les accès aux données SQL Server ou Cache mémoire.

    Espérant que ce post vous sera utile !

    mercredi 11 octobre 2006 15:26
  • merci pour votre rapidité ;)

    je vais traduire ceci en VB...
    faire des tests

    ceci dit je bosse en 2.0 mais j'ai trouvé des choses interessantes ici
    http://msdn2.microsoft.com/fr-fr/library/system.globalization.cultureinfo.currentuiculture.aspx

    je n'ai pas bien compris l'histoire de la base, mais je vais m'y pencher...

    merci a vous

    mercredi 11 octobre 2006 16:08
  • Pour avoir plus d'explication sur l'utilisation du ResourceManager : http://msdn2.microsoft.com/fr-fr/library/system.resources.resourcemanager.aspx
    mercredi 11 octobre 2006 16:16
  • Bonjour

     

    Sauf grosse erreur de ma part, je pense avoir trouvé le plus simple, je m'explique

    attention je suis en .net 2.0

    Je créer x fichiers de ressources global je les noment Data.resx, Data.es.resx etc...

    Je met dedans les nom de mes champs.

    Je modifie ma requete lors de l'init du SqlDataSource avec un truc du genre

        Protected Sub SqlDataSource1_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles SqlDataSource1.Init


            SqlDataSource1.SelectCommand = "SELECT [ProdID], [ProdRef], " + Resources.Data.ProduitLibelle + ", [ProdImage] FROM [Produits]"

        End Sub

    J'ai testé cela marche bien mais peut-être que je n'ai pas pensé à tous.

     

    merci de vos remarques

     

     

    mardi 17 octobre 2006 18:01
  • Bonjour,

    La méthode de modifier les requêtes à la volée fonctionne bien effectivement mais il est mieux de pourvoir disposer d'un cache, comme avec le ResourceMabnager de Mr Arnaud Cleret, pour éviter de devoir faire les requêtes à chaqe pages. Cela offre un gain de temps indéniable et une économie du CPU pour de gros sites multilangues.


    .NET life
    if (this.Reply.HelpsYou)
    {
        MarkAsAnswer = true;
    }
    vendredi 6 août 2010 14:20
  • Bonjour Primactif,

    Est-ce que vous avez résolu votre problème ?

    Merci d’avance de tenir la communauté informée sur la suite de vos démarches.

    Cordialement,
    aelassas.free.fr
    vendredi 28 octobre 2011 22:45
    Auteur de réponse