Comment utiliser la localisation en C #

268

Je n'arrive pas à faire fonctionner la localisation.

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

Comment puis je faire ça?

JL.
la source
PS: assurez-vous que vous avez installé l'extension gratuite Microsoft MAT (Multilingual App Toolkit) pour Visual Studio ;-)
juFo

Réponses:

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

Exécutez ce code:

Console.WriteLine(Properties.strings.Hello);

Il devrait afficher "Bonjour".

Maintenant, ajoutez 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 (Name = "Hello", Value = "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);

Ce qui se passe, c'est que le système recherchera une ressource pour "fr-FR". Il n'en trouvera pas (puisque nous avons spécifié "fr" dans votre fichier "). Il reviendra alors à la recherche de" fr ", qu'il trouve (et utilise).

Le code suivant affichera "Bonjour":

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

C'est parce qu'il ne trouve aucune ressource "en-US", et également aucune ressource "en", donc il reviendra à la valeur par défaut, qui est 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 se replierait. Donc, si un texte est le même en France et au Canada, vous pouvez le mettre dans strings.fr.resx, tandis que des chaînes qui sont différentes en français canadien pourraient aller dans strings.fr-CA.resx.

Fredrik Mörk
la source
24
La réponse pourrait faire référence à la plomberie "en arrière-plan" qui est effectuée par Visual Studio ici: fichier resx.designer.cs, faisant fonctionner l'intellisense; assemblys satellites compilés avec la bibliothèque de classes, qui doivent être déployés avec l'assembly compilé et tous les projets ultérieurs qui l'utilisent, etc ... La réponse est agréable et simple, mais cela n'aide pas à expliquer où les choses pourraient mal tourner, par exemple si vous n'utilisez pas Visual Studio.
Tao
13
+1 message! Plutôt que de créer des fichiers manuellement, essayez Zeta Resource Editor ( zeta-resource-editor.com/index.html ). C'est gratuit et vous aide à faire ce genre de traductions BEAUCOUP plus rapidement que dans VS.
Killnine
4
Access Modifierdoit être défini Publicpour la classe de ressources à générer. La classe n'est pas nécessairement dans l'espace de noms Properties, c'est là que vous placez le fichier .resx.
Andrey Moiseev
3
Sachez que dans VS 2017 resx avec localisation dans winform ne fonctionne pas en raison d'un bogue (au moins jusqu'à la version 15.4). Un ticket est disponible: developercommunity.visualstudio.com/content/problem/63772/…
muccix
4
À partir de .NET 4.5, il est également possible d'utiliser System.Globalization.CultureInfo.DefaultThreadCurrentCulture au lieu de Thread.CurrentThread.CurrentUICulture de sorte que vous modifiez les paramètres régionaux pour l'application entière au lieu de thread par thread
GrixM
41

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

Maintenant, lorsque vous voulez ajouter, disons, la localisation allemande, ajoutez un fichier resx localisé. Ce sera généralement Strings.de.resxdans ce cas. Si vous souhaitez ajouter une localisation supplémentaire pour, disons, l'Autriche, vous devez également créer un fichier Strings.de-AT.resx.

Maintenant, allez créer 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 "Bonjour, Welt!". Et dans Strings.de-AT.resx, ajoutez "Servus, Welt!". C'est tout pour l'instant.

Vous avez maintenant cette Stringsclasse générée , et elle a une propriété avec un getter HelloWorld. Obtenir cette propriété chargera "Servus, Welt!" lorsque votre locale est de-AT, "Bonjour, Welt! lorsque votre locale est toute autre de locale (y compris de-DE et de-CH), et" Bonjour, monde! "lorsque votre locale est autre chose. Si une chaîne est manquant dans la version localisée, le gestionnaire de ressources remontera automatiquement la chaîne, de la ressource la plus spécialisée à la ressource invariante.

Vous pouvez utiliser la ResourceManagerclasse pour plus de contrôle sur la façon exacte dont vous chargez les choses. La Stringsclasse générée l' utilise également.

OregonGhost
la source
comment définir les paramètres régionaux?
Matheus Simon
1
@MatheusSimon: Vous n'en avez pas besoin. Par défaut, les paramètres régionaux actuels de l'utilisateur sont utilisés. Si vous souhaitez forcer une certaine locale (par exemple pour permettre aux utilisateurs de changer la langue manuellement), vous devez définir System.Threading.Thread.CurrentCulture et CurrentUICulture dans chaque thread , probablement avant le chargement des ressources pour la première fois. Il est plus facile de redémarrer une application pour cela plutôt que de la mettre à jour lors de l'exécution.
OregonGhost
15

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

  • Définissez la propriété du formulaire"Localizable" surtrue
  • Modifiez la Languagepropriété du formulaire dans la langue de votre choix (à partir d'une liste déroulante sympa avec tous)
  • Traduisez les commandes sous cette forme et déplacez-les si besoin est (écrasez ces très longues phrases en français!)

Modifier: cet article MSDN sur la localisation des formulaires Windows n'est pas l'original que j'ai lié ... mais pourrait apporter plus de lumière si nécessaire. (l'ancien a été enlevé)

noelicus
la source
L'article msdn n'est plus disponible, un remplacement?
fuomag9
Pas sûr - j'ai lié le meilleur que j'ai pu voir, mais je ne me souviens pas à quoi ressemblait l'article il y a 7 ans;)
noelicus
14

Excellente 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 le recompiler pour générer le resources.dll.

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

Supposons que vous ayez 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

Assurez-vous de conserver l'espace de noms d'origine dans les noms de fichiers (ici "WpfRibbonApplication1")

Eric Bole-Feysot
la source
2
Merci pour le commentaire sur la préservation de l'espace de noms (y) qui - s'il est manqué - ne générera aucune erreur, mais reviendra simplement à la ressource de secours.
Mosca Pt
11

Correction et élaboration de la réponse de @Fredrik Mörk .

  • Ajoutez un strings.resxfichier de ressources à votre projet (ou un nom de fichier différent)
  • Défini Access Modifiersur Public(dans l' strings.resxonglet fichier ouvert )
  • Ajoutez une ressource de chaîne dans le fichier resx: (exemple: nom Hello, valeur Hello)
  • Enregistrez le fichier de ressources

Visual Studio génère automatiquement une stringsclasse respective , qui est réellement placée dans strings.Designer.cs. La classe se trouve dans le même espace de noms que celui auquel vous vous attendez à ce qu'un nouveau .csfichier soit placé.

Ce code s'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 avec le même nom que précédemment, mais une valeur différente: (nom Hello, valeur Salut)

Le code suivant s'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. Apprenez-en plus ici .

Vous pouvez ajouter des ressources spécifiques au pays comme strings.fr-FR.resxou strings.fr-CA.resx.

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

  • À partir de ressources spécifiques au pays comme strings.fr-CA.resx
  • À partir de ressources spécifiques à la langue comme strings.fr.resx
  • Par défaut strings.resx

Notez que les ressources spécifiques au langage génèrent des assemblys satellites .

Découvrez également comment CurrentCulturediffère d' CurrentUICulture ici .

Andrey Moiseev
la source
1

Dans mon cas

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

dans AssemblyInfo.cs a empêché les choses de fonctionner comme d'habitude.

Aleksandr
la source
0

En plus de la réponse @Eric Bole-Feysot :

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

  • le code source (projet VS) pourrait être séparé du projet de langue,
  • l'ajout d'une nouvelle langue ne nécessite pas de recompiler le projet,
  • la traduction pourrait être effectuée 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 basée sur des fichiers .dll / .exe. En fait, en interne (dans le répertoire du projet de langage), il crée / gère des versions localisées de fichiers resx et compile un assemblage de la même manière que @Eric Bole-Feysot décrit.

Tomasz Malik
la source
0

ResourceManager et .resx sont un peu désordonnés.

Vous pouvez utiliser Lexical.Localization ¹ qui permet d'incorporer des valeurs par défaut et des valeurs spécifiques à la culture dans le code, et d'être étendu dans des fichiers de localisation externes pour d'autres cultures (comme .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) );
    }
}

¹ (je suis le mainteneur de cette bibliothèque)

Marque
la source
0

En général, vous mettez vos traductions dans des fichiers de ressources, par exemple resources.resx.

Chaque culture spécifique a un nom différent, par exemple resources.nl.resx, resources.fr.resx, resources.de.resx,…

Maintenant, la partie la plus importante d'une solution est de maintenir vos traductions. Dans Visual Studio, installez l'outil Microsoft MAT: Multilingual App Toolkit (MAT). Fonctionne avec winforms, wpf, asp.net (core), uwp,…

En général, par exemple pour une solution WPF, dans le projet WPF

  • Installez l'extension Microsoft MAT pour Visual Studio.
  • Dans l'Explorateur de solutions, accédez à votre projet> Propriétés> AssemblyInfo.cs
  • Ajoutez dans AssemblyInfo.cs votre langue neutre par défaut (dans mon cas, l'anglais): [assembly: System.Resources.NeutralResourcesLanguage("en")]
  • Sélectionnez votre projet dans l'Explorateur de solutions et dans Visual Studio, dans le menu supérieur, cliquez sur "Outils"> "Boîte à outils d'application multilingue"> "Activer la sélection", pour activer MAT pour le projet.
    • Maintenant, cliquez avec le bouton droit de la souris sur le projet dans l'Explorateur de solutions, sélectionnez «Boîte à outils d'applications multilingues»> «Ajouter des langues de traduction…» et sélectionnez la langue pour laquelle vous souhaitez ajouter des traductions. par exemple néerlandais.

Ce que vous verrez, c'est qu'un nouveau dossier sera créé, appelé "MultilingualResources" contenant un ....nl.xlffichier.

La seule chose que vous devez faire maintenant est:

  1. ajoutez votre traduction à votre fichier resources.resx par défaut (dans mon cas, l'anglais)
  2. Traduisez en cliquant sur le fichier .xlf (PAS sur le fichier .resx) car les fichiers .xlf généreront / mettront à jour les fichiers .resx.

(les fichiers .xlf devraient s'ouvrir avec "l'éditeur multilingue", si ce n'est pas le cas, faites un clic droit sur le fichier .xlf, sélectionnez "Ouvrir avec…" et sélectionnez "éditeur multilingue".

S'amuser! maintenant, vous pouvez également voir ce qui n'a pas été traduit, exporter les traductions dans xlf vers des sociétés de traduction externes, les réimporter, recycler les traductions d'autres projets, etc.

Plus d'informations:

juFo
la source