LocalisationLocalization

Télécharger l’exemple Télécharger l’exempleDownload Sample Download the sample

Vous pouvez localiser les applications Xamarin.Forms à l’aide de fichiers de ressources.NET.Xamarin.Forms apps can be localized using .NET resources files.

Vue d'ensembleOverview

Le mécanisme intégré de localisation des applications .NET utilise des fichiers RESX ainsi que les classes des espaces de noms System.Resources et System.Globalization.The built-in mechanism for localizing .NET applications uses RESX files and the classes in the System.Resources and System.Globalization namespaces. Les fichiers RESX contenant les chaînes traduites sont incorporés dans l’assembly Xamarin.Forms, ainsi qu’une classe générée par le compilateur qui fournit un accès fortement typé aux traductions.The RESX files containing translated strings are embedded in the Xamarin.Forms assembly, along with a compiler-generated class that provides strongly-typed access to the translations. Vous pouvez ensuite récupérer le texte traduit dans le code.The translated text can then be retrieved in code.

Exemple de codeSample Code

Deux exemples sont associés à ce document :There are two samples associated with this document:

  • UsingResxLocalization est une démonstration très simple des concepts expliqués.UsingResxLocalization is a very simple demonstration of the concepts explained. Les extraits de code ci-dessous proviennent tous de cet exemple.The code snippets shown below are all from this sample.
  • TodoLocalized est une application de travail de base qui utilise ces techniques de localisation.TodoLocalized is a basic working app that uses these localization techniques.

L’exemple TodoLocalized inclut une version de démonstration de projet partagé. Toutefois, en raison des limitations du système de build, les fichiers de ressources ne disposent pas d’un fichier .designer.cs généré, ce qui empêche d’accéder aux chaînes traduites fortement typées dans le code.The TodoLocalized sample includes a Shared Project demo however due to limitations of the build system the resource files do not get a .designer.cs file generated which breaks the ability to access translated strings strongly-typed in code.

Le reste de ce document concerne les projets basés sur le modèle de bibliothèque Xamarin.Forms .NET Standard.The remainder of this document relates to projects using the Xamarin.Forms .NET Standard library template.

Globalisation du code de Xamarin.FormsGlobalizing Xamarin.Forms Code

La globalisation d’une application consiste à la rendre « internationale ».Globalizing an application is the process of making it "world ready." Cela signifie écrire du code capable d’afficher différentes langues.This means writing code that is capable of displaying different languages.

L’un des éléments clés de la globalisation d’une application est la génération de l’interface utilisateur sans texte codé en dur.One of the key parts of globalizing an application is building the user-interface so that there is no hard-coded text. À la place, tout ce qui est affiché à l’utilisateur doit être récupéré à partir d’un ensemble de chaînes traduites dans la langue choisie.Instead, anything displayed to the user should be retrieved from a set of strings that have been translated into their chosen language.

Dans ce document, nous allons voir comment utiliser les fichiers RESX pour stocker ces chaînes et les récupérer afin de les afficher en fonction des préférences de l’utilisateur.In this document we'll examine how to use RESX files to store those strings and retrieve them for display depending on the user's preference.

Les exemples ciblent l’anglais, le français, l’espagnol, l’allemand, le chinois, le japonais, le russe et le portugais (Brésil).The samples target English, French, Spanish, German, Chinese, Japanese, Russian, and Brazilian Portuguese languages. Vous pouvez traduire les applications en autant de langues que nécessaire.Applications can be translated into as few or as many languages as required.

Notes

Sur la plateforme Windows universelle, les fichiers RESW doivent être utilisés pour la localisation des notifications Push, à la place des fichiers RESX.On the Universal Windows Platform, RESW files should be used for push notification localization, rather than RESX files. Pour plus d’informations, consultez Localisation UWP.For more information, see UWP Localization.

Ajout de ressourcesAdding Resources

La première étape de la globalisation d’une application de bibliothèque Xamarin.Forms .NET Standard consiste à ajouter les fichiers de ressources RESX destinés à stocker l’ensemble du texte utilisé dans l’application.The first step in globalizing a Xamarin.Forms .NET Standard library application is adding the RESX resource files that will be used to store all the text used in the app. Nous devons ajouter un fichier RESX contenant le texte par défaut, puis ajouter des fichiers RESX supplémentaires pour chaque langue que nous souhaitons prendre en charge.We need to add a RESX file that contains the default text, and then add additional RESX files for each language we wish to support.

Ressource de langue de baseBase Language Resource

Le fichier de ressources de base (RESX) contient les chaînes de langue par défaut (les exemples partent du principe que l’anglais est la langue par défaut).The base resources (RESX) file will contain the default language strings (the samples assume English is the default language). Ajoutez le fichier au projet de code commun Xamarin.Forms en cliquant avec le bouton droit sur le projet, puis en choisissant Ajouter > Nouveau fichier.Add the file to the Xamarin.Forms common code project by right-clicking on the project and choosing Add > New File....

Choisissez un nom explicite, par exemple AppResources, puis appuyez sur OK.Choose a meaningful name such as AppResources and press OK.

Ajouter un fichier de ressourcesAdd Resource File

Deux fichiers sont ajoutés au projet :Two files will be added to the project:

  • AppResources.resx, un fichier dans lequel les chaînes traduisibles sont stockées au format XMLAppResources.resx file where translatable strings are stored in an XML format.
  • AppResources.designer.cs, un fichier qui déclare une classe partielle contenant des références à tous les éléments créés dans le fichier XML RESXAppResources.designer.cs file that declares a partial class to contain references to all the elements created in the RESX XML file.

L’arborescence de la solution montre les fichiers liés.The solution tree will show the files as related. Vous devez modifier le fichier RESX pour ajouter de nouvelles chaînes traduisibles. Le fichier .designer.cs ne doit pas être modifié.The RESX file should be edited to add new translatable strings; the .designer.cs file should not be edited.

Visibilité des chaînesString Visibility

Par défaut, quand des références aux chaînes fortement typées sont générées, elles sont internal pour l’assembly.By default when strongly-typed references to strings are generated, they will be internal to the assembly. En effet, l’outil de build par défaut pour les fichiers RESX génère le fichier .designer.cs avec des propriétés internal.This is because the default build tool for RESX files generates the .designer.cs file with internal properties.

Sélectionnez le fichier AppResources.resx, puis affichez le panneau Propriétés pour voir où cet outil de build est configuré.Select the AppResources.resx file and show the Properties pad to see where this build tool is configure. La capture d’écran ci-dessous montre l’outil personnalisé : ResXFileCodeGenerator.The screenshot below shows the Custom Tool: ResXFileCodeGenerator.

Pour rendre public les propriétés de chaîne fortement typées, vous devez changer manuellement la configuration en Outil personnalisé : PublicResXFileCodeGenerator, comme indiqué dans la capture d’écran ci-dessous :To make the strongly-typed string properties public, you must manually change the configuration to Custom Tool: PublicResXFileCodeGenerator, as shown in the screenshot below:

Ce changement est facultatif. Il est obligatoire uniquement si vous souhaitez référencer des chaînes localisées dans différents assemblys (par exemple, si vous placez les fichiers RESX dans un autre assembly de votre code).This change is optional, and is only required if you wish to reference localized strings across different assemblies (for example, if you put the RESX files in a different assembly to your code). L’exemple de cette rubrique laisse les chaînes internal, car elles sont définies dans le même assembly de bibliothèque Xamarin.Forms .NET Standard que celui où elles sont utilisées.The sample for this topic leaves the strings internal because they are defined in the same Xamarin.Forms .NET Standard library assembly where they are used.

Il vous suffit de définir l’outil personnalisé dans le fichier RESX de base, comme indiqué ci-dessus. Vous n’avez pas besoin de définir un outil de build pour les fichiers RESX spécifiques à la langue décrits dans les sections suivantes.You only need to set the custom tool on the base RESX file as shown above; you do not need to set any build tool on the language-specific RESX files discussed in the following sections.

Modification du fichier RESXEditing the RESX file

Malheureusement, il n’existe pas d’éditeur RESX intégré dans Visual Studio pour Mac.Unfortunately there is no built-in RESX editor in Visual Studio for Mac. L’ajout de nouvelles chaînes traduisibles nécessite l’ajout d’un nouvel élément data XML pour chaque chaîne.Adding new translatable strings requires the addition of a new XML data element for each string. Chaque élément data peut contenir ce qui suit :Each data element can contain the following:

  • L’attribut name (obligatoire), qui est la clé de cette chaîne à traduire.name attribute (required) is the key for this translatable string. Il doit s’agir d’un nom de propriété C# valide. Aucun espace ni caractère spécial n’est donc autorisé.It must be a valid C# property name - so no spaces or special characters are allowed.
  • L’élément value (obligatoire), qui correspond à la chaîne réelle affichée dans l’application.value element (required), which is the actual string that is displayed in the application.
  • L’élément comment (facultatif), qui peut contenir des instructions à l’intention du traducteur pour expliquer comment cette chaîne est utilisée.comment element (optional) can contain instructions for the translator that explains how this string is used.
  • L’attribut xml:space (facultatif), qui permet de contrôler la façon dont l’espacement est conservé dans la chaîne.xml:space attribute (optional) to control how spacing in the string is preserved.

Quelques exemples d’éléments data sont présentés ici :Some example data elements are shown here:

<data name="NotesLabel" xml:space="preserve">
    <value>Notes:</value>
    <comment>label for input field</comment>
</data>
<data name="NotesPlaceholder" xml:space="preserve">
    <value>eg. buy milk</value>
    <comment>example input for notes field</comment>
</data>
<data name="AddButton" xml:space="preserve">
    <value>Add new item</value>
</data>

Au fur et à mesure de l’écriture de l’application, chaque texte affiché à l’utilisateur doit être ajouté au fichier de ressources RESX de base dans un nouvel élément data.As the application is written, every piece of text displayed to the user should be added to the base RESX resources file in a new data element. Il est recommandé d’inclure les comment autant que possible pour garantir une traduction de haute qualité.It is recommended that you include comments as much as possible to ensure a high-quality translation.

Notes

Visual Studio (notamment l’édition gratuite Community) contient un éditeur RESX de base.Visual Studio (including the free Community edition) contains a basic RESX editor. Si vous avez accès à un ordinateur Windows, cela peut être un moyen pratique d’ajouter et de modifier des chaînes dans des fichiers RESX.If you have access to a Windows computer, that can be a convenient way to add and edit strings in RESX files.

Ressources spécifiques aux languesLanguage-Specific Resources

En règle générale, la traduction réelle des chaînes de caractères par défaut n’a pas lieu tant que de grands blocs de l’application n’ont pas été écrits (dans ce cas, le fichier RESX par défaut contient de nombreuses chaînes).Typically, the actual translation of the default text strings won't happen until large chunks of the application have been written (in which case the default RESX file will contain lots of strings). Il est toujours judicieux d’ajouter les ressources spécifiques à une langue au début du cycle de développement, en incluant éventuellement du texte traduit automatiquement pour permettre le test du code de localisation.It is still a good idea to add the language-specific resources early in the development cycle, optionally populating with machine-translated text to help test the localization code.

Un fichier RESX supplémentaire est ajouté pour chaque langue que nous souhaitons prendre en charge.One additional RESX file is added for each language we wish to support. Les fichiers de ressources spécifiques à une langue doivent respecter une convention de nommage particulière : utilisez le même nom de fichier que le fichier de ressources de base (par exempleLanguage-specific resource files must follow a specific naming convention: use the same filename as the base resources file (eg. AppResources) suivi d’un point (.) et du code de langue.AppResources) followed by a period (.) and then the language code. Voici quelques exemples simples :Simple examples include:

  • AppResources.fr.resx - Traductions en français.AppResources.fr.resx - French language translations.
  • AppResources.es.resx - Traductions en espagnol.AppResources.es.resx - Spanish language translations.
  • AppResources.de.resx - Traductions en allemand.AppResources.de.resx - German language translations.
  • AppResources.ja.resx - Traductions en japonais.AppResources.ja.resx - Japanese language translations.
  • AppResources.zh-Hans.resx - Traductions en chinois (simplifié).AppResources.zh-Hans.resx - Chinese (Simplified) language translations.
  • AppResources.zh-Hant.resx - Traductions en chinois (traditionnel).AppResources.zh-Hant.resx - Chinese (Traditional) language translations.
  • AppResources.pt.resx - Traductions en portugais.AppResources.pt.resx - Portuguese language translations.
  • AppResources.pt-BR.resx - Traductions en portugais (Brésil).AppResources.pt-BR.resx - Brazilian Portuguese language translations.

Le modèle général consiste à utiliser des codes de langue à deux lettres, mais il existe des exemples (par exemple le chinois) où un autre format est utilisé, et d’autres exemples (par exemple le portugais parlé au Brésil) où un identificateur de paramètres régionaux à quatre caractères est nécessaire.The general pattern is to use two-letter language codes, but there are some examples (such as Chinese) where a different format is used, and other examples (such as Brazilian Portuguese) where a four character locale identifier is required.

Ces fichiers de ressources spécifiques à la langue ne nécessitent pas de classe partielle .designer.cs. Ils peuvent donc être ajoutés en tant que fichiers XML classiques, avec l’action de génération : EmbeddedResource définie.These language-specific resources files do not require a .designer.cs partial class so they can be added as regular XML files, with the Build Action: EmbeddedResource set. Cette capture d’écran montre une solution contenant des fichiers de ressources spécifiques à la langue :This screenshot shows a solution containing language-specific resource files:

Quand vous développez une application et que vous ajoutez du texte au fichier RESX de base, vous devez l’envoyer aux traducteurs pour qu’ils traduisent chaque élément data et retournent un fichier de ressources spécifique à la langue (selon la convention de nommage indiquée) afin de l’inclure dans l’application.As an application is developed and the base RESX file has text added, you should send it out to translators who will translate each data element and return a language-specific resource file (using the naming convention shown) to be included in the app. Voici quelques exemples de « traduction automatique » ci-dessous :Some 'machine translated' examples are shown below:

AppResources.es.resx (espagnol)AppResources.es.resx (Spanish)

<data name="AddButton" xml:space="preserve">
    <value>Escribir un artículo</value>
    <comment>this string appears on a button to add a new item to the list</comment>
</data>

AppResources.ja.resx (japonais)AppResources.ja.resx (Japanese)

<data name="AddButton" xml:space="preserve">
    <value>新しい項目を追加</value>
    <comment>this string appears on a button to add a new item to the list</comment>
</data>

AppResources.pt-BR.resx (portugais parlé au Brésil)AppResources.pt-BR.resx (Brazilian Portuguese)

<data name="AddButton" xml:space="preserve">
    <value>adicionar novo item</value>
    <comment>this string appears on a button to add a new item to the list</comment>
</data>

Seul l’élément value doit être mis à jour par le traducteur, l’élément comment n’est pas destiné à être traduit.Only the value element needs to be updated by the translator - the comment is not intended to be translated. N’oubliez pas : quand vous modifiez des fichiers XML, utilisez des séquences d’échappement pour les caractères réservés, par exemple utilisez <, >, & avec &lt;, &gt; et &amp;, s’ils apparaissent dans value ou comment.Remember: when editing XML files to escape reserved characters like <, >, & with &lt;, &gt;, and &amp; if they appear in the value or comment.

Utilisation de ressources dans le codeUsing Resources in Code

Les chaînes des fichiers de ressources RESX sont utilisables dans le code de votre interface utilisateur via la classe AppResources.Strings in the RESX resource files will be available to use in your user interface code using the AppResources class. Le name affecté à chaque chaîne du fichier RESX devient une propriété de cette classe qui peut être référencée dans le code de Xamarin.Forms, comme indiqué ci-dessous :The name assigned to each string in the RESX file becomes a property on that class which can be referenced in Xamarin.Forms code as shown below:

var myLabel = new Label ();
var myEntry = new Entry ();
var myButton = new Button ();
// populate UI with translated text values from resources
myLabel.Text = AppResources.NotesLabel;
myEntry.Placeholder = AppResources.NotesPlaceholder;
myButton.Text = AppResources.AddButton;

L’interface utilisateur sur iOS, Android et UWP (plateforme Windows universelle) se présente comme vous le souhaitez, sauf qu’il est maintenant possible de traduire l’application en plusieurs langues, car le texte est chargé à partir d’une ressource au lieu d’être codé en dur.The user interface on iOS, Android, and the Universal Windows Platform (UWP) renders as you'd expect, except now it's possible to translate the app into multiple languages because the text is being loaded from a resource rather than being hard-coded. Voici une capture d’écran montrant l’IU sur chaque plateforme avant la traduction :Here is a screenshot showing the UI on each platform prior to translation:

Résolution des problèmesTroubleshooting

Test d’une langue spécifiqueTesting a Specific Language

Il peut s’avérer difficile de faire passer le simulateur ou un appareil dans d’autres langues, en particulier durant la phase de développement, quand vous souhaitez tester rapidement différentes cultures.It can be tricky to switch the simulator or a device to different languages, particularly during development when you want to test different cultures quickly.

Vous pouvez forcer le chargement d’une langue spécifique en définissant Culture comme indiqué dans l’extrait de code suivant :You can force a specific language to be loaded by setting the Culture as shown in this code snippet:

// force a specific culture, useful for quick testing
AppResources.Culture =  new CultureInfo("fr-FR");

Vous pouvez également utiliser cette approche (définir la culture directement sur la classe AppResources) pour implémenter un sélecteur de langue dans votre application (au lieu d’utiliser les paramètres régionaux de l’appareil).This approach – setting the culture directly on the AppResources class – can also be used to implement a language-selector inside your app (rather than using the device's locale).

Chargement des ressources incorporéesLoading Embedded Resources

L’extrait de code suivant est utile quand vous essayez de déboguer des problèmes relatifs à des ressources incorporées (par exemple des fichiers RESX).The following code snippet is useful when trying to debug issues with embedded resources (such as RESX files). Ajoutez ce code à votre application (au début de son cycle de vie). Il va lister toutes les ressources incorporées dans l’assembly, en affichant l’identificateur complet de la ressource :Add this code to your app (early in the app lifecycle) and it will list all the resources embedded in the assembly, showing the full resource identifier:

using System.Reflection;
// ...
// NOTE: use for debugging, not in released app code!
var assembly = typeof(EmbeddedImages).GetTypeInfo().Assembly; // "EmbeddedImages" should be a class in your app
foreach (var res in assembly.GetManifestResourceNames())
{
    System.Diagnostics.Debug.WriteLine("found resource: " + res);
}

Dans le fichier AppResources.Designer.cs (vers la ligne 33), le nom du gestionnaire des ressources est spécifié dans son intégralité (par exempleIn the AppResources.Designer.cs file (around line 33), the full resource manager name is specified (eg. "UsingResxLocalization.Resx.AppResources") à l’image du code ci-dessous :"UsingResxLocalization.Resx.AppResources") similar to the code below:

System.Resources.ResourceManager temp =
        new System.Resources.ResourceManager(
                "UsingResxLocalization.Resx.AppResources",
                typeof(AppResources).GetTypeInfo().Assembly);

Examinez dans la sortie de l’application les résultats du code de débogage présenté ci-dessus pour vérifier que les ressources appropriées sont listées (à savoir "UsingResxLocalization.Resx.AppResources").Check the Application Output for the results of the debug code shown above, to confirm the correct resources are listed (ie. "UsingResxLocalization.Resx.AppResources").

Si ce n’est pas le cas, la classe AppResources ne peut pas charger ses ressources.If not, the AppResources class will be unable to load its resources. Consultez ce qui suit pour résoudre les problèmes de ressources introuvables :Check the following to resolve issues where the resources cannot be found:

  • L’espace de noms par défaut du projet correspond à l’espace de noms racine du fichier AppResources.Designer.cs.The default namespace for the project matches the root namespace in the AppResources.Designer.cs file.
  • Si le fichier AppResources.resx est situé dans un sous-répertoire, le nom de ce sous-répertoire doit faire partie de l’espace de noms et de l’identificateur de ressource.If the AppResources.resx file is located in a subdirectory, the subdirectory name should be part of the namespace and part of the resource identifier.
  • Le fichier AppResources.resx comporte l’Action de génération : EmbeddedResource.The AppResources.resx file has Build Action: EmbeddedResource.
  • La case Options du projet > Code source > Stratégies de noms .NET > Utiliser des noms de ressource de style Visual Studio est cochée.The Project Options > Source Code > .NET Naming Policies > Use Visual Studio-style resources names is ticked. Vous pouvez la décocher si vous le souhaitez. Toutefois, les espaces de noms utilisés pour référencer vos ressources RESX doivent être mis à jour dans l’application.You can untick this if you prefer, however the namespaces used when referencing your RESX resources will need to updated throughout the app.

Ne fonctionne pas en mode DÉBOGAGE (Android uniquement)Doesn't work in DEBUG mode (Android only)

Si les chaînes traduites fonctionnent correctement dans vos builds Android de MISE EN PRODUCTION mais pas pendant le débogage, cliquez avec le bouton droit sur Projet Android, sélectionnez Options > Build > Build Android, puis vérifiez que l’option Déploiement d’assembly rapide n’est PAS cochée.If the translated strings are working in your RELEASE Android builds but not while debugging, right-click on the Android Project and select Options > Build > Android Build and ensure that the Fast assembly deployment is NOT ticked. Cette option entraîne des problèmes de chargement de ressources. Vous ne devez pas l’utiliser si vous testez des applications localisées.This option causes problems with loading resources and should not be used if you are testing localized apps.

Affichage de la langue appropriéeDisplaying the Correct Language

Jusqu’ici, nous avons vu comment écrire du code pour permettre l’utilisation de traductions, mais pas comment les faire apparaître.So far we've examined how to write code so that translations can be provided, but not how to actually make them appear. Le code de Xamarin.Forms peut tirer parti des ressources de .NET pour charger les traductions linguistiques appropriées. Toutefois, nous devons interroger le système d’exploitation de chaque plateforme pour déterminer quelle est la langue sélectionnée par l’utilisateur.Xamarin.Forms code can take advantage of .NET's resources to load the correct language translations, but we need to query the operating system on each platform to determine which language the user has selected.

Dans la mesure où du code spécifique à la plateforme est nécessaire pour obtenir la préférence linguistique de l’utilisateur, utilisez un service de dépendance afin d’exposer ces informations dans l’application Xamarin.Forms et de les implémenter pour chaque plateforme.Because some platform-specific code is required to obtain the user's language preference, use a dependency service to expose that information in the Xamarin.Forms app and implement it for each platform.

Commencez par définir une interface pour exposer la culture par défaut de l’utilisateur, à l’image du code ci-dessous :First, define an interface to expose the user's preferred culture, similar to the code below:

public interface ILocalize
{
    CultureInfo GetCurrentCultureInfo ();
    void SetLocale (CultureInfo ci);
}

Utilisez ensuite le DependencyService de la classe App de Xamarin.Forms pour appeler l’interface et affecter la valeur appropriée à la culture de nos ressources RESX.Second, use the DependencyService in the Xamarin.Forms App class to call the interface and set our RESX resources culture to the correct value. Notez que nous n’avons pas besoin de définir manuellement cette valeur pour la plateforme Windows universelle, car le framework de ressources reconnaît automatiquement la langue sélectionnée sur ces plateformes.Notice that we don't need to manually set this value for the Universal Windows Platform, since the resources framework automatically recognizes the selected language on those platforms.

if (Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.Android)
{
    var ci = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();
    Resx.AppResources.Culture = ci; // set the RESX for resource localization
    DependencyService.Get<ILocalize>().SetLocale(ci); // set the Thread for locale-aware methods
}

La ressource Culture doit être définie au premier chargement de l’application pour permettre l’utilisation des chaînes de langue appropriées.The resource Culture needs to be set when the application first loads so that the correct language strings are used. Vous pouvez éventuellement mettre à jour cette valeur en fonction d’événements spécifiques à la plateforme susceptibles d’être générés sur iOS ou sur Android, si l’utilisateur met à jour ses préférences linguistiques pendant l’exécution de l’application.You may optionally update this value according to platform-specific events that may be raised on iOS or Android if the user updates their language preferences while the app is running.

Les implémentations de l’interface ILocalize sont présentées dans la section Code spécifique à la plateforme ci-dessous.The implementations for the ILocalize interface are shown in the Platform-specific Code section below. Ces implémentations tirent parti de la classe d’assistance PlatformCulture :These implementations take advantage of this PlatformCulture helper class:

public class PlatformCulture
{
    public PlatformCulture (string platformCultureString)
    {
        if (String.IsNullOrEmpty(platformCultureString))
        {
            throw new ArgumentException("Expected culture identifier", "platformCultureString"); // in C# 6 use nameof(platformCultureString)
        }
        PlatformString = platformCultureString.Replace("_", "-"); // .NET expects dash, not underscore
        var dashIndex = PlatformString.IndexOf("-", StringComparison.Ordinal);
        if (dashIndex > 0)
        {
            var parts = PlatformString.Split('-');
            LanguageCode = parts[0];
            LocaleCode = parts[1];
        }
        else
        {
            LanguageCode = PlatformString;
            LocaleCode = "";
        }
    }
    public string PlatformString { get; private set; }
    public string LanguageCode { get; private set; }
    public string LocaleCode { get; private set; }
    public override string ToString()
    {
        return PlatformString;
    }
}

Code spécifique à la plateformePlatform-Specific Code

Le code permettant de détecter la langue à afficher doit être spécifique à la plateforme, car iOS, Android et UWP exposent ces informations de manière légèrement différente.The code to detect which language to display must be platform-specific because iOS, Android, and UWP all expose this information in slightly different ways. Le code du service de dépendance ILocalize est fourni ci-dessous pour chaque plateforme. Il est accompagné d’exigences supplémentaires spécifiques à la plateforme pour garantir un affichage correct du texte localisé.The code for the ILocalize dependency service is provided below for each platform, along with additional platform-specific requirements to ensure localized text is rendered correctly.

Le code spécifique à la plateforme doit également gérer les cas où le système d’exploitation permet à l’utilisateur de configurer un identificateur de paramètres régionaux non pris en charge par la classe CultureInfo de .NET.The platform-specific code must also handle cases where the operating system allows the user to configure a locale identifier that is not supported by .NET's CultureInfo class. Dans ces cas de figure, vous devez écrire du code personnalisé pour détecter les paramètres régionaux non pris en charge et les remplacer par des paramètres régionaux compatibles .NET.In these cases custom code must be written to detect unsupported locales and substitute the best .NET-compatible locale.

Projet d’application iOSiOS Application Project

Les utilisateurs iOS sélectionnent leur langue par défaut séparément de la culture de mise en forme de la date et de l’heure.iOS users select their preferred language separately from date and time formatting culture. Pour charger les ressources appropriées afin de localiser une application Xamarin.Forms, il nous suffit d’interroger le premier élément du tableau NSLocale.PreferredLanguages.To load the correct resources to localize a Xamarin.Forms app we just need to query the NSLocale.PreferredLanguages array for the first element.

L’implémentation suivante du service de dépendance ILocalize doit être placée dans le projet d’application iOS.The following implementation of the ILocalize dependency service should be placed in the iOS application project. Dans la mesure où iOS utilise des traits de soulignement au lieu de tirets (ce qui correspond à la représentation .NET Standard), le code remplace le trait de soulignement avant d’instancier la classe CultureInfo :Because iOS uses underscores instead of dashes (which is the .NET standard representation) the code replaces the underscore before instantiating the CultureInfo class:

[assembly:Dependency(typeof(UsingResxLocalization.iOS.Localize))]

namespace UsingResxLocalization.iOS
{
    public class Localize : UsingResxLocalization.ILocalize
    {
        public void SetLocale (CultureInfo ci)
        {
            Thread.CurrentThread.CurrentCulture = ci;
            Thread.CurrentThread.CurrentUICulture = ci;
        }

        public CultureInfo GetCurrentCultureInfo ()
        {
            var netLanguage = "en";
            if (NSLocale.PreferredLanguages.Length > 0)
            {
                var pref = NSLocale.PreferredLanguages [0];
                netLanguage = iOSToDotnetLanguage(pref);
            }
            // this gets called a lot - try/catch can be expensive so consider caching or something
            System.Globalization.CultureInfo ci = null;
            try
            {
                ci = new System.Globalization.CultureInfo(netLanguage);
            }
            catch (CultureNotFoundException e1)
            {
                // iOS locale not valid .NET culture (eg. "en-ES" : English in Spain)
                // fallback to first characters, in this case "en"
                try
                {
                    var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
                    ci = new System.Globalization.CultureInfo(fallback);
                }
                catch (CultureNotFoundException e2)
                {
                    // iOS language not valid .NET culture, falling back to English
                    ci = new System.Globalization.CultureInfo("en");
                }
            }
            return ci;
        }

        string iOSToDotnetLanguage(string iOSLanguage)
        {
            // .NET cultures don't support underscores
            string netLanguage = iOSLanguage.Replace("_", "-");

            //certain languages need to be converted to CultureInfo equivalent
            switch (iOSLanguage)
            {
                case "ms-MY":   // "Malaysian (Malaysia)" not supported .NET culture
                case "ms-SG":    // "Malaysian (Singapore)" not supported .NET culture
                    netLanguage = "ms"; // closest supported
                    break;
                case "gsw-CH":  // "Schwiizertüütsch (Swiss German)" not supported .NET culture
                    netLanguage = "de-CH"; // closest supported
                    break;
                // add more application-specific cases here (if required)
                // ONLY use cultures that have been tested and known to work
            }
            return netLanguage;
        }

        string ToDotnetFallbackLanguage (PlatformCulture platCulture)
        {
            var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars, usually);
            switch (platCulture.LanguageCode)
            {
                case "pt":
                    netLanguage = "pt-PT"; // fallback to Portuguese (Portugal)
                    break;
                case "gsw":
                    netLanguage = "de-CH"; // equivalent to German (Switzerland) for this app
                    break;
                // add more application-specific cases here (if required)
                // ONLY use cultures that have been tested and known to work
            }
            return netLanguage;
        }
    }
}

Notes

Les blocs try/catch de la méthode GetCurrentCultureInfo reproduisent le comportement de secours utilisé généralement avec les spécificateurs de paramètres régionaux : si la correspondance exacte est introuvable, une correspondance étroite doit être recherchée uniquement en fonction de la langue (premier bloc de caractères des paramètres régionaux).The try/catch blocks in the GetCurrentCultureInfo method mimic the fallback behavior typically used with locale specifiers – if the exact match is not found, look for a close match based just on the language (first block of characters in the locale).

Dans le cas de Xamarin.Forms, certains paramètres régionaux sont valides dans iOS mais ne correspondent pas à un CultureInfo valide dans .NET. Le code ci-dessus tente de répondre à cette situation.In the case of Xamarin.Forms, some locales are valid in iOS but do not correspond to a valid CultureInfo in .NET, and the code above attempts to handle this.

Par exemple, l’écran iOS Réglages > Général Langue & Région vous permet de configurer la Langue de votre téléphone en choisissant Anglais mais comme vous avez défini la Région à Espagne, cela donne la chaîne de paramètres régionaux "en-ES".For example, the iOS Settings > General Language & Region screen allows you to set your phone Language to English but the Region to Spain, which results in a locale string of "en-ES". En cas d’échec de la création de CultureInfo, le code utilise uniquement les deux premières lettres pour sélectionner la langue d’affichage.When the CultureInfo creation fails, the code falls back to using just the first two letters to select the display language.

Les développeurs doivent modifier les méthodes iOSToDotnetLanguage et ToDotnetFallbackLanguage pour prendre en compte les cas spécifiques liés aux langues prises en charge.Developers should modify the iOSToDotnetLanguage and ToDotnetFallbackLanguage methods to handle specific cases required for their supported languages.

Certains éléments d’interface utilisateur définis par le système sont automatiquement traduits par iOS, par exemple le bouton OK du contrôle Picker.There are some system-defined user-interface elements that are automatically translated by iOS, such as the Done button on the Picker control. Pour forcer iOS à traduire ces éléments, nous devons indiquer les langues que nous prenons en charge dans le fichier Info.plist.To force iOS to translate these elements we need to indicate which languages we support in the Info.plist file. Vous pouvez ajouter ces valeurs via Info.plist > Source, comme indiqué ici :You can add these values via Info.plist > Source as shown here:

Clés de localisation dans Info.plistLocalization keys in Info.plist

Vous pouvez également ouvrir le fichier Info.plist dans un éditeur XML et modifier directement les valeurs :Alternatively, open the Info.plist file in an XML editor and edit the values directly:

<key>CFBundleLocalizations</key>
<array>
    <string>de</string>
    <string>es</string>
    <string>fr</string>
    <string>ja</string>
    <string>pt</string> <!-- Brazil -->
    <string>pt-PT</string> <!-- Portugal -->
    <string>ru</string>
    <string>zh-Hans</string>
    <string>zh-Hant</string>
</array>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>

Une fois que vous avez mis en place le service de dépendance et mis à jour le fichier Info.plist, l’application iOS peut afficher le texte localisé.Once you've implemented the dependency service and updated Info.plist, the iOS app will be able to display localized text.

Notes

Notez qu’Apple traite le portugais de manière légèrement différente.Note that Apple treats Portuguese slightly differently than you'd expect. D’après la documentation : « Utilisez pt en tant qu’ID de langue pour le portugais utilisé au Brésil, et pt-PT en tant qu’ID de langue pour le portugais utilisé au Portugal » .From their docs: "use pt as the language ID for Portuguese as it is used in Brazil and pt-PT as the language ID for Portuguese as it is used in Portugal". En d’autres termes, quand vous choisissez la langue portugaise dans des paramètres régionaux non standard, la langue de secours est le portugais parlé au Brésil sur iOS, à moins d’écrire du code pour changer ce comportement (par exemple ToDotnetFallbackLanguage ci-dessus).This means when Portuguese language is chosen in a non-standard locale, the fallback language will be Brazilian Portuguese on iOS, unless code is written to change this behavior (such as the ToDotnetFallbackLanguage above).

Pour plus d’informations sur la localisation iOS, consultez Localisation iOS.For more information about iOS Localization, see iOS Localization.

Projet d’application AndroidAndroid Application Project

Android expose les paramètres régionaux sélectionnés via Java.Util.Locale.Default et utilise également le trait de soulignement comme séparateur au lieu du tiret (qui est remplacé par le code suivant).Android exposes the currently selected locale via Java.Util.Locale.Default, and also uses an underscore separator instead of a dash (which is replaced by the following code). Ajoutez cette implémentation du service de dépendance au projet d’application Android :Add this dependency service implementation to the Android application project:

[assembly:Dependency(typeof(UsingResxLocalization.Android.Localize))]

namespace UsingResxLocalization.Android
{
    public class Localize : UsingResxLocalization.ILocalize
    {
        public void SetLocale(CultureInfo ci)
        {
            Thread.CurrentThread.CurrentCulture = ci;
            Thread.CurrentThread.CurrentUICulture = ci;
        }
        public CultureInfo GetCurrentCultureInfo()
        {
            var netLanguage = "en";
            var androidLocale = Java.Util.Locale.Default;
            netLanguage = AndroidToDotnetLanguage(androidLocale.ToString().Replace("_", "-"));
            // this gets called a lot - try/catch can be expensive so consider caching or something
            System.Globalization.CultureInfo ci = null;
            try
            {
                ci = new System.Globalization.CultureInfo(netLanguage);
            }
            catch (CultureNotFoundException e1)
            {
                // iOS locale not valid .NET culture (eg. "en-ES" : English in Spain)
                // fallback to first characters, in this case "en"
                try
                {
                    var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
                    ci = new System.Globalization.CultureInfo(fallback);
                }
                catch (CultureNotFoundException e2)
                {
                    // iOS language not valid .NET culture, falling back to English
                    ci = new System.Globalization.CultureInfo("en");
                }
            }
            return ci;
        }
        string AndroidToDotnetLanguage(string androidLanguage)
        {
            var netLanguage = androidLanguage;
            //certain languages need to be converted to CultureInfo equivalent
            switch (androidLanguage)
            {
                case "ms-BN":   // "Malaysian (Brunei)" not supported .NET culture
                case "ms-MY":   // "Malaysian (Malaysia)" not supported .NET culture
                case "ms-SG":   // "Malaysian (Singapore)" not supported .NET culture
                    netLanguage = "ms"; // closest supported
                    break;
                case "in-ID":  // "Indonesian (Indonesia)" has different code in  .NET
                    netLanguage = "id-ID"; // correct code for .NET
                    break;
                case "gsw-CH":  // "Schwiizertüütsch (Swiss German)" not supported .NET culture
                    netLanguage = "de-CH"; // closest supported
                    break;
                    // add more application-specific cases here (if required)
                    // ONLY use cultures that have been tested and known to work
            }
            return netLanguage;
        }
        string ToDotnetFallbackLanguage(PlatformCulture platCulture)
        {
            var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars, usually);
            switch (platCulture.LanguageCode)
            {
                case "gsw":
                    netLanguage = "de-CH"; // equivalent to German (Switzerland) for this app
                    break;
                    // add more application-specific cases here (if required)
                    // ONLY use cultures that have been tested and known to work
            }
            return netLanguage;
        }
    }
}

Notes

Les blocs try/catch de la méthode GetCurrentCultureInfo reproduisent le comportement de secours utilisé généralement avec les spécificateurs de paramètres régionaux : si la correspondance exacte est introuvable, une correspondance étroite doit être recherchée uniquement en fonction de la langue (premier bloc de caractères des paramètres régionaux).The try/catch blocks in the GetCurrentCultureInfo method mimic the fallback behavior typically used with locale specifiers – if the exact match is not found, look for a close match based just on the language (first block of characters in the locale).

Dans le cas de Xamarin.Forms, certains paramètres régionaux sont valides dans Android mais ne correspondent pas à un CultureInfo valide dans .NET. Le code ci-dessus tente de répondre à cette situation.In the case of Xamarin.Forms, some locales are valid in Android but do not correspond to a valid CultureInfo in .NET, and the code above attempts to handle this.

Les développeurs doivent modifier les méthodes iOSToDotnetLanguage et ToDotnetFallbackLanguage pour prendre en compte les cas spécifiques liés aux langues prises en charge.Developers should modify the iOSToDotnetLanguage and ToDotnetFallbackLanguage methods to handle specific cases required for their supported languages.

Une fois ce code ajouté au projet d’application Android, il peut afficher automatiquement les chaînes traduites.Once this code has been added to the Android application project, it will be able to automatically display translated strings.

Avertissement

Si les chaînes traduites fonctionnent correctement dans vos builds Android de MISE EN PRODUCTION mais pas pendant le débogage, cliquez avec le bouton droit sur Projet Android, sélectionnez Options > Build > Build Android, puis vérifiez que l’option Déploiement d’assembly rapide n’est PAS cochée.If the translated strings are working in your RELEASE Android builds but not while debugging, right-click on the Android Project and select Options > Build > Android Build and ensure that the Fast assembly deployment is NOT ticked. Cette option entraîne des problèmes de chargement de ressources. Vous ne devez pas l’utiliser si vous testez des applications localisées.This option causes problems with loading resources and should not be used if you are testing localized apps.

Pour plus d’informations sur la localisation Android, consultez Localisation Android.For more information about Android localization, see Android Localization.

Plateforme Windows universelleUniversal Windows Platform

Les projets UWP (plateforme Windows universelle) ne nécessitent pas le service de dépendance.Universal Windows Platform (UWP) projects do not require the dependency service. À la place, cette plateforme définit automatiquement la culture de la ressource de manière appropriée.Instead, this platform automatically sets the resource's culture correctly.

AssemblyInfo.csAssemblyInfo.cs

Développez le nœud Propriétés du projet de bibliothèque .NET Standard, puis double-cliquez sur le fichier AssemblyInfo.cs.Expand the Properties node in the .NET Standard library project and double-click on the AssemblyInfo.cs file. Ajoutez la ligne suivante au fichier pour définir l’anglais comme langue de ressources neutres de l’assembly :Add the following line to the file to set the neutral resources assembly language to English:

[assembly: NeutralResourcesLanguage("en")]

Cela permet d’informer le Gestionnaire des ressources de la culture par défaut de l’application. Ainsi, les chaînes définies dans le fichier RESX indépendant de la langue (AppResources.resx) sont correctement affichées quand l’application s’exécute avec l’un des paramètres régionaux anglais.This informs the resource manager of the app's default culture, therefore ensuring that the strings defined in the language neutral RESX file (AppResources.resx) will be displayed when the app is running in one the English locales.

ExemplesExample

Après la mise à jour des projets spécifiques à la plateforme, comme indiqué ci-dessus, et la recompilation de l’application avec les fichiers RESX traduits, les traductions mises à jour sont disponibles dans chaque application.After updating the platform-specific projects as shown above and recompiling the app with translated RESX files, updated translations will be available in each app. Voici une capture d’écran de l’exemple de code traduit en chinois simplifié :Here is a screenshot from the sample code translated into Simplified Chinese:

Pour plus d’informations sur la localisation UWP, consultez Localisation UWP.For more information about UWP localization, see UWP Localization.

Localisation XAMLLocalizing XAML

Durant la génération d’une interface utilisateur Xamarin.Forms en XAML, le code de balise ressemble à ceci, avec des chaînes incorporées directement en XML :When building a Xamarin.Forms user interface in XAML the markup would look similar to this, with strings embedded directly in the XML:

<Label Text="Notes:" />
<Entry Placeholder="eg. buy milk" />
<Button Text="Add to list" />

Dans l’idéal, nous pouvons traduire les contrôles d’interface utilisateur directement dans le code XAML, en créant une extension de balisage.Ideally, we could translate user interface controls directly in the XAML, which we can do by creating a markup extension. Le code d’une extension de balisage qui expose les ressources RESX au format XAML est présenté ci-dessous.The code for a markup extension that exposes the RESX resources to XAML is shown below. Vous devez ajouter cette classe au code commun de Xamarin.Forms (avec les pages XAML) :This class should be added to the Xamarin.Forms common code (along with the XAML pages):

using System;
using System.Globalization;
using System.Reflection;
using System.Resources;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace UsingResxLocalization
{
    // You exclude the 'Extension' suffix when using in XAML
    [ContentProperty("Text")]
    public class TranslateExtension : IMarkupExtension
    {
        readonly CultureInfo ci = null;
        const string ResourceId = "UsingResxLocalization.Resx.AppResources";

        static readonly Lazy<ResourceManager> ResMgr = new Lazy<ResourceManager>(
            () => new ResourceManager(ResourceId, IntrospectionExtensions.GetTypeInfo(typeof(TranslateExtension)).Assembly));

        public string Text { get; set; }

        public TranslateExtension()
        {
            if (Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.Android)
            {
                ci = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();
            }
        }

        public object ProvideValue(IServiceProvider serviceProvider)
        {
            if (Text == null)
                return string.Empty;

            var translation = ResMgr.Value.GetString(Text, ci);
            if (translation == null)
            {
#if DEBUG
                throw new ArgumentException(
                    string.Format("Key '{0}' was not found in resources '{1}' for culture '{2}'.", Text, ResourceId, ci.Name),
                    "Text");
#else
                translation = Text; // HACK: returns the key, which GETS DISPLAYED TO THE USER
#endif
            }
            return translation;
        }
    }
}

Les puces suivantes expliquent les éléments importants du code ci-dessus :The following bullets explain the important elements in the code above:

  • La classe s’appelle TranslateExtension, mais par convention, nous pouvons y faire référence à l’aide de Translate dans notre code de balise.The class is named TranslateExtension, but by convention we can refer to is as Translate in our markup.
  • La classe implémente IMarkupExtension, qui est nécessaire au bon fonctionnement de Xamarin.Forms.The class implements IMarkupExtension, which is required by Xamarin.Forms for it to work.
  • "UsingResxLocalization.Resx.AppResources" sert d’identificateur de ressource pour nos ressources RESX."UsingResxLocalization.Resx.AppResources" is the resource identifier for our RESX resources. Il se compose de notre espace de noms par défaut, du dossier dans lequel se trouvent les fichiers de ressources et du nom de fichier RESX par défaut.It is comprised of our default namespace, the folder where the resource files are located and the default RESX filename.
  • La classe ResourceManager est créée à l’aide de IntrospectionExtensions.GetTypeInfo(typeof(TranslateExtension)).Assembly) pour déterminer l’assembly actuel à partir duquel les ressources sont chargées. Cette classe est mise en cache dans le champ statique ResMgr.The ResourceManager class is created using IntrospectionExtensions.GetTypeInfo(typeof(TranslateExtension)).Assembly) to determine the current assembly to load resources from, and cached in the static ResMgr field. Elle est créée en tant que type Lazy pour que sa création soit différée jusqu’à sa première utilisation dans la méthode ProvideValue.It's created as a Lazy type so that its creation is deferred until it's first used in the ProvideValue method.
  • ci utilise le service de dépendance pour déterminer la langue choisie par l’utilisateur à partir du système d’exploitation natif.ci uses the dependency service to get the user's chosen language from the native operating system.
  • GetString est la méthode qui récupère la chaîne réelle traduite à partir des fichiers de ressources.GetString is the method that retrieves the actual translated string from the resources files. Sur la plateforme Windows universelle, ci a une valeur null, car l’interface ILocalize n’est pas implémentée sur ces plateformes.On the Universal Windows Platform, ci will be null because the ILocalize interface isn't implemented on those platforms. Cela équivaut à appeler la méthode GetString avec seulement le premier paramètre.This is equivalent to calling the GetString method with only the first parameter. À la place, le framework de ressources reconnaît automatiquement les paramètres régionaux et récupère la chaîne traduite à partir du fichier RESX approprié.Instead, the resources framework will automatically recognize the locale and will retrieve the translated string from the appropriate RESX file.
  • La gestion des erreurs a été incluse pour permettre le débogage des ressources manquantes en levant une exception (en mode DEBUG uniquement).Error handling has been included to help debug missing resources by throwing an exception (in DEBUG mode only).

L’extrait XAML suivant montre comment utiliser l’extension de balisage.The following XAML snippet shows how to use the markup extension. Deux étapes sont nécessaires à son fonctionnement :There are two steps to make it work:

  1. Déclarez l’espace de noms personnalisé xmlns:i18n dans le nœud racine.Declare the custom xmlns:i18n namespace in the root node. namespace et assembly doivent correspondre exactement aux paramètres de projet. Dans cet exemple, ils sont identiques mais ils peuvent être différents dans votre projet.The namespace and assembly must match the project settings exactly - in this example they are identical but could be different in your project.
  2. Utilisez la syntaxe {Binding} pour les attributs qui contiennent normalement du texte afin d’appeler l’extension de balisage Translate.Use {Binding} syntax on attributes that would normally contain text to call the Translate markup extension. La clé de ressource est le seul paramètre obligatoire.The resource key is the only required parameter.
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="UsingResxLocalization.FirstPageXaml"
        xmlns:i18n="clr-namespace:UsingResxLocalization;assembly=UsingResxLocalization">
    <StackLayout Padding="0, 20, 0, 0">
        <Label Text="{i18n:Translate NotesLabel}" />
        <Entry Placeholder="{i18n:Translate NotesPlaceholder}" />
        <Button Text="{i18n:Translate AddButton}" />
    </StackLayout>
</ContentPage>

La syntaxe plus détaillée suivante est également valide pour l’extension de balisage :The following more verbose syntax is also valid for the markup extension:

<Button Text="{i18n:TranslateExtension Text=AddButton}" />

Localisation d’éléments spécifiques à la plateformeLocalizing Platform-Specific Elements

Bien que nous puissions prendre en charge la traduction de l’interface utilisateur dans le code de Xamarin.Forms, certains éléments doivent être traduits dans chaque projet spécifique à la plateforme.Although we can handle the translation of the user interface in Xamarin.Forms code, there are some elements that must be done in each platform-specific project. Cette section décrit la localisation :This section will cover how to localize:

  • Application NameApplication Name
  • ImagesImages

L’exemple de projet inclut une image localisée appelée flag.png, référencée en C# comme suit :The sample project includes a localized image called flag.png, which is referenced in C# as follows:

var flag = new Image();
switch (Device.RuntimePlatform)
{
    case Device.iOS:
    case Device.Android:
        flag.Source = ImageSource.FromFile("flag.png");
        break;
    case Device.UWP:
        flag.Source = ImageSource.FromFile("Assets/Images/flag.png");
        break;
}

L’image du drapeau est également référencée en XAML comme suit :The flag image is also referenced in the XAML like this:

<Image>
  <Image.Source>
    <OnPlatform x:TypeArguments="ImageSource">
        <On Platform="iOS, Android" Value="flag.png" />
        <On Platform="UWP" Value="Assets/Images/flag.png" />
    </OnPlatform>
  </Image.Source>
</Image>

Toutes les plateformes résolvent automatiquement les références d’images de ce type en versions localisées des images, à condition que les structures de projet décrites ci-dessous soient implémentées.All platforms will automatically resolve image references like these to localized versions of the images, as long as the project structures explained below are implemented.

Projet d’application iOSiOS Application Project

iOS utilise un standard de nommage pour désigner les répertoires qui contiennent les ressources d’images et de chaînes : il s’agit des répertoires de projets de localisation ou des répertoires .lproj.iOS uses a naming standard called Localization Projects or .lproj directories to contain image and string resources. Ces répertoires peuvent contenir des versions localisées des images utilisées dans l’application ainsi que le fichier InfoPlist.strings qui permet de localiser le nom de l’application.These directories can contain localized versions of images used in the app, and also the InfoPlist.strings file that can be used to localize the app name. Pour plus d’informations sur la localisation iOS, consultez Localisation iOS.For more information about iOS Localization, see iOS Localization.

ImagesImages

Cette capture d’écran montre l’exemple d’application iOS et les répertoires .lproj spécifiques à la langue.This screenshot shows the iOS sample app with language-specific .lproj directories. Le répertoire espagnol appelé es.lproj contient les versions localisées de l’image par défaut ainsi que flag.png :The Spanish directory called es.lproj, contains localized versions of the default image, as well as flag.png:

Chaque répertoire de langue contient une copie de flag.png localisée pour cette langue.Each language directory contains a copy of flag.png, localized for that language. Si aucune image n’est fournie, le système d’exploitation utilise par défaut l’image du répertoire de langue par défaut.If no image is supplied, the operating system will default to the image in the default language directory. Pour une prise en charge complète de Retina, vous devez fournir des copies @2x et @3x de chaque image.For full Retina support, you should supply @2x and @3x copies of each image.

Nom de l’applicationApp Name

Le contenu du fichier InfoPlist.strings correspond simplement à une paire clé-valeur qui permet de configurer le nom de l’application :The contents of the InfoPlist.strings is just a single key-value to configure the app name:

"CFBundleDisplayName" = "ResxEspañol";

Quand l’application s’exécute, le nom et l’image de l’application sont tous deux localisés :When the application is run, the app name and the image are both localized:

Projet d’application AndroidAndroid Application Project

Android suit un autre schéma pour stocker les images localisées. Il utilise des répertoires drawable et strings distincts avec un suffixe de code de langue.Android follows a different scheme for storing localized images using different drawable and strings directories with a language code suffix. Quand un code de paramètres régionaux à quatre lettres doit être fourni (par exemple zh-TW ou pt-BR), Android nécessite l’ajout d’un r après le tiret/avant le code de paramètres régionaux (par exempleWhen a four-letter locale code is required (such as zh-TW or pt-BR), note that Android requires an additional r following the dash/preceding the locale code (eg. zh-rTW ou pt-rBR).zh-rTW or pt-rBR). Pour plus d’informations sur la localisation Android, consultez Localisation Android.For more information about Android localization, see Android Localization.

ImagesImages

Cette capture d’écran montre l’exemple Android avec des Drawables et des chaînes localisés :This screenshot shows the Android sample with a some localized drawables and strings:

Notez qu’Android n’utilise pas les codes zh-Hans et zh-Hant pour le chinois simplifié et le chinois traditionnel. À la place, il prend en charge uniquement les codes zh-CN et zh-TW spécifiques au pays.Note that Android does not use zh-Hans and zh-Hant codes for Simplified and Traditional Chinese; instead, it only supports country-specific codes zh-CN and zh-TW.

Pour permettre la prise en charge des différentes résolutions d’images sur les écrans haute densité, créez des dossiers de langue supplémentaires avec les suffixes -*dpi, par exemple drawables-es-mdpi, drawables-es-xdpi, drawables-es-xxdpi, etc. Pour plus d’informations, consultez Fourniture de ressources Android de remplacement.To support different resolution images for high-density screens, create additional language folders with -*dpi suffixes, such as drawables-es-mdpi, drawables-es-xdpi, drawables-es-xxdpi, etc. See Providing Alternative Android Resources for more information.

Nom de l’applicationApp Name

Le contenu du fichier strings.xml correspond simplement à une paire clé-valeur qui permet de configurer le nom de l’application :The contents of the strings.xml is just a single key-value to configure the app name:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">ResxEspañol</string>
</resources>

Mettez à jour MainActivity.cs dans le projet d’application Android pour que Label référence le code XML des chaînes.Update the MainActivity.cs in the Android app project so that the Label references the strings XML.

[Activity (Label = "@string/app_name", MainLauncher = true,
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]

L’application localise désormais l’image et le nom de l’application.The app now localizes the app name and image. Voici une capture d’écran du résultat (en espagnol) :Here's a screenshot of the result (in Spanish):

Projets d’application de la plateforme Windows universelleUniversal Windows Platform Application Projects

La plateforme Windows universelle comporte une infrastructure de ressources qui simplifie la localisation des images et du nom de l’application.The Universal Windows Platform possesses a resource infrastructure that simplifies the localization of images and the app name. Pour plus d’informations sur la localisation UWP, consultez Localisation UWP.For more information about UWP localization, see UWP Localization.

ImagesImages

Vous pouvez localiser les images en les plaçant dans un dossier spécifique à la ressource, comme illustré dans la capture d’écran suivante :Images can be localized by placing them in a resource-specific folder, as demonstrated in the following screenshot:

Au moment de l’exécution, l’infrastructure de ressources Windows sélectionne l’image appropriée en fonction des paramètres régionaux de l’utilisateur.At runtime the Windows resource infrastructure will select the appropriate image based on the user's locale.

RécapitulatifSummary

Vous pouvez localiser les applications Xamarin.Forms à l’aide de fichiers RESX et de classes de globalisation .NET.Xamarin.Forms applications can be localized using RESX files and .NET globalization classes. À l’exception d’une petite portion de code spécifique à la plateforme pour détecter la langue préférée par l’utilisateur, l’essentiel de l’effort de localisation est centralisé dans le code commun.Apart from a small amount of platform-specific code to detect what language the user prefers, most of the localization effort is centralized in the common code.

Les images sont généralement gérées de manière spécifique à la plateforme pour tirer parti de la prise en charge multirésolution fournie dans iOS et Android.Images are generally handled in a platform-specific way to take advantage of the multi-resolution support provided in both iOS and Android.