web-dev-qa-db-fra.com

Localiser les chaînes en Javascript

J'utilise actuellement des fichiers .resx pour gérer mes ressources côté serveur pour .NET.

l'application que je traite permet également aux développeurs de brancher JavaScript dans divers gestionnaires d'événements pour la validation côté client, etc. Quel est le meilleur moyen pour moi de localiser mes messages et chaînes JavaScript? 

Idéalement, j'aimerais stocker les chaînes dans les fichiers .resx pour les conserver avec le reste des ressources localisées.

Je suis ouvert aux suggestions.

38
SaaS Developer

Un objet JavaScript de base est un tableau associatif, il peut donc être facilement utilisé pour stocker des paires clé/valeur. Donc, en utilisant JSON , vous pouvez créer un objet pour chaque chaîne à localiser comme ceci:

var localizedStrings={
    confirmMessage:{
        'en/US':'Are you sure?',
        'fr/FR':'Est-ce que vous êtes certain?',
        ...
    },

    ...
}

Ensuite, vous pouvez obtenir la version locale de chaque chaîne comme ceci:

var locale='en/US';
var confirm=localizedStrings['confirmMessage'][locale];
25
Joel Anair

Inspiré par SproutCore Vous pouvez définir les propriétés des chaînes :

'Hello'.fr = 'Bonjour';
'Hello'.es = 'Hola';

et ensuite, crachez simplement la localisation appropriée en fonction de vos paramètres régionaux:

var locale = 'en';
alert( message[locale] );
13
Ryan

Après avoir beaucoup cherché sur Google et ne pas être satisfait de la majorité des solutions présentées, je viens de trouver une solution générique/géniale qui utilise modèles T4 . Le message complet de Jochen van Wylick vous pouvez lire ici:

Utilisation de T4 pour la localisation de ressources JavaScript basées sur des fichiers .resx

Les principaux avantages sont:

  1. N'avoir qu'un seul endroit où les ressources sont gérées (à savoir les fichiers .resx )
  2. Prise en charge de plusieurs cultures
  3. Exploitation d'IntelliSense - permet de compléter le code

Désavantages:

Les inconvénients de cette solution sont bien sûr la taille du fichier Le fichier .js peut devenir assez volumineux. Cependant, puisqu'il est mis en cache par le navigateur, nous ne considérons pas cela comme un problème pour notre application. Toutefois - Cette mise en cache peut également empêcher le navigateur de trouver la ressource appelée à partir de code.


Comment ça marche?

En gros, il a défini un modèle T4 qui pointe vers vos fichiers .resx. Avec du code C #, il parcourt chaque chaîne de ressources et l'ajoute à des propriétés de valeur de clé pure JavaScript, qui sont ensuite affichées dans un fichier JavaScript unique appelé Resources.js (vous pouvez modifier les noms si vous le souhaitez).


Modèle T4 [changez en conséquence pour pointer sur l'emplacement de vos fichiers .resx]

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ Assembly name="System.Windows.Forms" #>
<#@ import namespace="System.Resources" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.IO" #>
<#@ output extension=".js"#>
<#
 var path = Path.GetDirectoryName(Host.TemplateFile) + "/../App_GlobalResources/";
 var resourceNames = new string[1]
 {
  "Common"
 };

#>
/**
* Resources
* ---------
* This file is auto-generated by a tool
* 2012 Jochen van Wylick
**/
var Resources = {
 <# foreach (var name in resourceNames) { #>
 <#=name #>: {},
 <# } #>
};
<# foreach (var name in resourceNames) {
 var nlFile = Host.ResolvePath(path + name + ".nl.resx" );
 var enFile = Host.ResolvePath(path + name + ".resx" );
 ResXResourceSet nlResxSet = new ResXResourceSet(nlFile);
 ResXResourceSet enResxSet = new ResXResourceSet(enFile);
#>

<# foreach (DictionaryEntry item in nlResxSet) { #>
Resources.<#=name#>.<#=item.Key.ToString()#> = {
 'nl-NL': '<#= ("" + item.Value).Replace("\r\n", string.Empty).Replace("'","\\'")#>',
 'en-GB': '<#= ("" + enResxSet.GetString(item.Key.ToString())).Replace("\r\n", string.Empty).Replace("'","\\'")#>'
 };
<# } #>
<# } #>

Du côté formulaire/vue

Pour que la traduction correcte soit récupérée, ajoutez ceci dans votre maquette si vous utilisez WebForms:

<script type="text/javascript">

    var locale = '<%= System.Threading.Thread.CurrentThread.CurrentCulture.Name %>';

</script>

<script type="text/javascript" src="/Scripts/Resources.js"></script>

Si vous utilisez ASP.NET MVC (comme moi), vous pouvez procéder comme suit:

<script type="text/javascript">

    // Setting Locale that will be used by JavaScript translations
    var locale = $("meta[name='accept-language']").attr("content");

</script>

<script type="text/javascript" src="/Scripts/Resources.js"></script>

L’assistant MetaAcceptLanguage que j’ai reçu de cet article génial de Scott Hanselman:

Mondialisation, internationalisation et localisation dans ASP.NET MVC 3, JavaScript et jQuery - Partie 1

public static IHtmlString MetaAcceptLanguage<T>(this HtmlHelper<T> html)
{
     var acceptLanguage =
         HttpUtility.HtmlAttributeEncode(
                     Thread.CurrentThread.CurrentUICulture.ToString());

      return new HtmlString(
      String.Format("<meta name=\"{0}\" content=\"{1}\">", "accept-language",
                    acceptLanguage));
 }

Utilise le

var msg = Resources.Common.Greeting[locale];
alert(msg);
10
Leniel Maccaferri

JSGettext fait un excellent travail - chargement dynamique de fichiers .po GNU Gettext en utilisant à peu près n'importe quelle langue sur le backend. Google pour "Localisation Javascript dynamique avec Gettext et PHP" pour trouver une procédure pas à pas pour JSGettext avec PHP (je posterais le lien, mais ce site idiot ne me laissera pas, soupir ...)

Edit: this devrait être le lien

4
Jani Patokallio

J'utiliserais une notation objet/tableau:

var phrases={};
phrases['fatalError'] ='On no!';

Ensuite, vous pouvez simplement échanger le fichier JS ou utiliser un appel Ajax pour redéfinir votre liste de phrases.

Avec un assembly satellite (au lieu d'un fichier resx), vous pouvez énumérer toutes les chaînes du serveur, où vous connaissez le langage, générant ainsi un objet Javascript avec uniquement les chaînes du langage correct. 

Quelque chose comme ça marche pour nous (code VB.NET):

Dim rm As New ResourceManager([resource name], [your Assembly])
Dim rs As ResourceSet = 
    rm.GetResourceSet(Thread.CurrentThread.CurrentCulture, True, True)
For Each kvp As DictionaryEntry In rs
    [Write out kvp.Key and kvp.Value]
Next

Malheureusement, nous n'avons pas encore trouvé le moyen de le faire pour les fichiers .resx.

4
Erik Hesselink

Il existe une bibliothèque pour localiser les applications JavaScript: https://github.com/wikimedia/jquery.i18n

Il peut effectuer le remplacement de paramètres, prendre en charge le genre (manipulation intelligente), le nombre (gestion intelligente du pluriel, y compris les langues ayant plusieurs formes de pluriel) et les règles de grammaire personnalisées dont certaines langues ont besoin.

Les chaînes sont stockées dans des fichiers JSON.

La seule exigence est jQuery.

3
Amir E. Aharoni

J'ai procédé comme suit pour localiser le code JavaScript d'une application mobile exécutant HTML5:

1.Créé un ensemble de fichiers de ressources pour chaque langue en les appelant comme "en.js" pour l'anglais. Chacune contenait les différentes chaînes de l'application comme suit:


        var localString = {
        appName: "your app name",
        message1: "blah blah"
      };

2.Utilisez Lazyload pour charger le fichier de ressources approprié en fonction de la langue de l'environnement local de l'application: https://github.com/rgrove/lazyload

3.Passez le code de langue via une chaîne de requête (à mesure que je lance le fichier html depuis Android à l'aide de PhoneGap)

4.Puis j'ai écrit le code suivant pour charger dynamiquement le fichier de ressource approprié:


var lang = getQueryString("language");
localization(lang);
function localization(languageCode) {
    try {
        var defaultLang = "en";
        var resourcesFolder = "values/";
        if(!languageCode || languageCode.length == 0)
            languageCode = defaultLang;
        // var LOCALIZATION = null;
        LazyLoad.js(resourcesFolder + languageCode + ".js", function() {
            if( typeof LOCALIZATION == 'undefined') {
                LazyLoad.js(resourcesFolder + defaultLang + ".js", function() {
                    for(var propertyName in LOCALIZATION) {
                        $("#" + propertyName).html(LOCALIZATION[propertyName]);
                    }
                });
            } else {
                for(var propertyName in LOCALIZATION) {
                    $("#" + propertyName).html(LOCALIZATION[propertyName]);
                }
            }
        });
    } catch (e) {
        errorEvent(e);
    }
}
function getQueryString(name)
{
  name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
  var regexS = "[\\?&]" + name + "=([^&#]*)";
  var regex = new RegExp(regexS);
  var results = regex.exec(window.location.href);
  if(results == null)
    return "";
  else
    return decodeURIComponent(results[1].replace(/\+/g, " "));
}

5.Dans le fichier html, je me réfère aux chaînes comme suit:


    span id="appName"
2
Jaime Botero

Eh bien, je pense que vous pouvez considérer cela. Exemple anglais-espagnol:

Écrivez 2 scripts Js, comme ça:

en-GB.js
lang = {
    date_message: 'The start date is incorrect',
    ...
};
es-ES.js
lang = {
    date_message: 'Fecha de inicio incorrecta',
    ...
};

Côté serveur - code derrière: 

Protected Overrides Sub InitializeCulture()
    Dim sLang As String 
    sLang = "es-ES" 

    Me.Culture = sLang
    Me.UICulture = sLang
    Page.ClientScript.RegisterClientScriptInclude(sLang & ".js", "../Scripts/" & sLang & ".js")

    MyBase.InitializeCulture()
End Sub

Où sLang pourrait être "en-GB", vous savez, selon la sélection de l'utilisateur actuel ...

Appels Javascript:

alert (lang.date_message);

Et cela fonctionne, très facile, je pense.

1
Caveman

Développer la réponse de diodeus.myopenid.com: Demandez à votre code d'écrire un fichier contenant un tableau JS avec toutes les chaînes requises, puis chargez le fichier/script approprié avant l'autre code JS. 

0
Lasar