web-dev-qa-db-fra.com

Comment utiliser la localisation en C #

Je n'arrive pas à faire en sorte que la localisation fonctionne. 

J'ai une bibliothèque de classe. Maintenant, je veux y créer des fichiers resx et y retourner des valeurs basées sur la culture du thread. 

Comment puis je faire ça?

245
JL.
  • Ajoutez un fichier de ressources à votre projet (vous pouvez l'appeler "strings.resx") en procédant comme suit: 
    Cliquez avec le bouton droit de la souris sur Propriétés dans le projet, sélectionnez Ajouter -> Nouvel élément ... dans le menu contextuel, puis dans la liste de Éléments Visual C # pick "Fichier de ressources" et nommez-le strings.resx.
  • Ajouter une ressource de chaîne dans le fichier resx et lui donner un bon nom (exemple: nommez-le "Hello" avec et donnez-lui la valeur "Hello")
  • Enregistrez le fichier de ressources ( note: ce sera le fichier default , car il n’a pas de code de langue à deux lettres)
  • Ajoutez des références à votre programme: System.Threading et System.Globalization

Exécutez ce code:

Console.WriteLine(Properties.strings.Hello);

Il devrait imprimer "Bonjour".

Ajoutez maintenant un nouveau fichier de ressources, nommé "strings.fr.resx" (notez la partie "fr"; celle-ci contiendra des ressources en français). Ajoutez une ressource de chaîne portant le même nom que dans strings.resx, mais avec la valeur en français (Nom = "Bonjour", Valeur = "Salut"). Maintenant, si vous exécutez le code suivant, il devrait imprimer Salut:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(Properties.strings.Hello);

En réalité, le système recherche une ressource pour "fr-FR". Il n'en trouvera pas (puisque nous avons spécifié "fr" dans votre fichier "). Il reviendra ensuite à la recherche de" fr "qu'il trouvera (et utilisera).

Le code suivant affichera "Bonjour":

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
Console.WriteLine(Properties.strings.Hello);

En effet, il ne trouve aucune ressource "en-US", ni aucune ressource "en". Elle revient donc à la valeur par défaut, celle que nous avons ajoutée depuis le début.

Vous pouvez créer des fichiers avec des ressources plus spécifiques si nécessaire (par exemple, strings.fr-FR.resx et strings.fr-CA.resx pour le français en France et au Canada, respectivement). Dans chacun de ces fichiers, vous devrez ajouter les ressources pour les chaînes qui diffèrent de la ressource à laquelle il tomberait. Donc, si un texte est identique en France et au Canada, vous pouvez le mettre dans strings.fr.resx, tandis que des chaînes différentes en français canadien pourraient aller dans strings.fr-CA.resx.

527
Fredrik Mörk

C'est assez simple, en fait. Créez un nouveau fichier de ressources, par exemple Strings.resx. Définissez Access Modifier sur Public. Utilisez le modèle de fichier approprié pour que Visual Studio génère automatiquement une classe d'accesseurs (le nom sera Strings, dans ce cas). Ceci est votre langue par défaut.

Maintenant, lorsque vous voulez ajouter, par exemple, la localisation allemande, ajoutez un fichier resx localisé. Ce sera typiquement Strings.de.resx dans ce cas. Si vous souhaitez ajouter une localisation supplémentaire pour, par exemple, l'Autriche, vous créerez en outre un Strings.de-AT.resx.

Maintenant, créez une chaîne - disons une chaîne avec le nom HelloWorld. Dans votre Strings.resx, ajoutez cette chaîne avec la valeur "Hello, world!". Dans Strings.de.resx, ajoutez "Hallo, Welt!". Et dans Strings.de-AT.resx, ajoutez "Servus, Welt!". C'est tout pour l'instant.

Vous avez maintenant cette classe Strings générée et elle a une propriété avec un getter HelloWorld. Obtenir cette propriété va charger "Servus, Welt!" lorsque vos paramètres régionaux sont de-AT, "Bonjour, Welt! lorsque vos paramètres régionaux sont n'importe quel autre paramètres régionaux (y compris de-DE et de-CH), et" Hello, World! "lorsque vos paramètres régionaux sont manquant dans la version localisée, le gestionnaire de ressources marchera automatiquement dans la chaîne, des ressources les plus spécialisées aux ressources invariantes.

Vous pouvez utiliser la classe ResourceManager pour plus de contrôle sur la manière dont vous chargez les choses. La classe Strings générée l'utilise également.

36
OregonGhost

Grande réponse de F.Mörk. Mais si vous souhaitez mettre à jour la traduction ou ajouter de nouvelles langues une fois l'application publiée, vous êtes bloqué car vous devez toujours la recompiler pour générer le fichier resources.dll.

Voici une solution pour compiler manuellement une dll ressource. Il utilise les outils resgen.exe et al.exe (installés avec le sdk).

Disons que vous avez un fichier de ressources Strings.fr.resx, vous pouvez compiler une dll de ressources avec le lot suivant:

resgen.exe /compile Strings.fr.resx,WpfRibbonApplication1.Strings.fr.resources 
Al.exe /t:lib /embed:WpfRibbonApplication1.Strings.fr.resources /culture:"fr" /out:"WpfRibbonApplication1.resources.dll"
del WpfRibbonApplication1.Strings.fr.resources
pause

Veillez à conserver l'espace de nom d'origine dans les noms de fichier (ici "WpfRibbonApplication1")

14
Eric Bole-Feysot

En plus de la réponse géniale de @Fredrik Mörk sur les chaînes, pour ajouter localisation à un formulaire, procédez comme suit:

  • Définissez la propriété form '"Localizable" sur true
  • Remplacez la propriété Language du formulaire par la langue de votre choix (dans un menu déroulant de Nice contenant tous les éléments entrants)
  • Traduisez les commandes sous cette forme et déplacez-les au besoin (écrasez ces très longues phrases complètes en français!)

Cet article MSDN sur la localisation de Windows Forms donne quelques informations supplémentaires à ce sujet.

14
noelicus

Un correctif et l'élaboration de la réponse @Fredrik Mörk.

  • Ajouter un fichier de ressource Strings.resx à votre projet (ou un autre nom de fichier)
  • Définissez Access Modifier sur Public (dans l'onglet du fichier Strings.resx ouvert)
  • Ajouter une ressource de chaîne dans le fichier resx: (exemple: nom Hello, valeur Hello)
  • Enregistrer le fichier de ressources

Visual Studio génère automatiquement une classe Strings respective, qui est en réalité placée dans Strings.Designer.cs. La classe se trouve dans le même espace de noms que celui dans lequel un fichier .cs nouvellement créé devrait être placé.

Ce code imprime toujours Hello, car il s’agit de la ressource par défaut et aucune ressource spécifique à la langue n’est disponible:

Console.WriteLine(Strings.Hello);

Ajoutez maintenant une nouvelle ressource spécifique à la langue:

  • Ajouter Strings.fr.resx (pour le français)
  • Ajoutez une chaîne portant le même nom que précédemment, mais avec une valeur différente: (nom Hello, valeur Salut)

Le code suivant imprime Salut:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(Strings.Hello);

La ressource utilisée dépend de Thread.CurrentThread.CurrentUICulture. Il est défini en fonction du paramètre de langue de l'interface utilisateur Windows ou peut être défini manuellement, comme dans cet exemple. En savoir plus sur ceci ici .

Vous pouvez ajouter des ressources spécifiques à un pays, telles que Strings.fr-FR.resx ou Strings.fr-CA.resx.

La chaîne à utiliser est déterminée dans cet ordre de priorité:

  • A partir d'une ressource spécifique à un pays telle que Strings.fr-CA.resx
  • A partir d'une ressource spécifique à la langue telle que Strings.fr.resx
  • Par défaut Strings.resx

Notez que les ressources spécifiques à une langue génèrent des assemblys satellites .

Découvrez également comment CurrentCulture diffère de CurrentUICultureici .

9
Andrey Moiseev

Dans mon cas

[Assembly: System.Resources.NeutralResourcesLanguage("ru-RU")]

dans AssemblyInfo.cs empêchait les choses de fonctionner comme d'habitude.

0
Aleksandr

ResourceManager et .resx sont un peu en désordre.

Vous pouvez utiliser Lexical.Localization qui permet d'incorporer des valeurs par défaut et spécifiques à une culture dans le code, et d'être étendu dans des fichiers de localisation externes pour des cultures ultérieures (telles que .json ou .resx).

public class MyClass
{
    /// <summary>
    /// Localization root for this class.
    /// </summary>
    static ILine localization = LineRoot.Global.Type<MyClass>();

    /// <summary>
    /// Localization key "Ok" with a default string, and couple of inlined strings for two cultures.
    /// </summary>
    static ILine ok = localization.Key("Success")
            .Text("Success")
            .fi("Onnistui")
            .sv("Det funkar");

    /// <summary>
    /// Localization key "Error" with a default string, and couple of inlined ones for two cultures.
    /// </summary>
    static ILine error = localization.Key("Error")
            .Format("Error (Code=0x{0:X8})")
            .fi("Virhe (Koodi=0x{0:X8})")
            .sv("Sönder (Kod=0x{0:X8})");

    public void DoOk()
    {
        Console.WriteLine( ok );
    }

    public void DoError()
    {
        Console.WriteLine( error.Value(0x100) );
    }
}
0
Tag

En plus de @Eric Bole-Feysot answer:

Grâce aux assemblages satellites, la localisation peut être créée à partir de fichiers .dll/.exe. Par ici: 

  • le code source (projet VS) peut être séparé du projet linguistique,
  • l'ajout d'une nouvelle langue ne nécessite pas de recompiler le projet,
  • la traduction peut être faite même par l'utilisateur final.

Il existe un outil peu connu appelé LSACreator (gratuit pour une utilisation non commerciale ou une option d'achat) qui vous permet de créer une localisation à partir de fichiers .dll/.exe. En fait, en interne (dans le répertoire du projet de langage), il crée/gère les versions localisées des fichiers resx et compile un assembly de la même manière que @Eric Bole-Feysot décrit.

0
Tomasz Malik