web-dev-qa-db-fra.com

Meilleures pratiques javascript et multilingue

quelle est la meilleure pratique pour un site Web multilingue utilisant DOM Manipulation avec javascript? Je crée des parties dynamiques du site Web en utilisant javascript. Ma première pensée a été d'utiliser un tableau avec les chaînes de texte et le code de langue comme index. Est-ce une bonne idée?

62
marquies

Quand j'ai déjà construit des sites multilingues (pas très grands, donc ça risque de ne pas évoluer trop bien), je garde une série de fichiers "langues":

  • lang.en.js
  • lang.it.js
  • lang.fr.js

Chacun des fichiers déclare un objet qui est fondamentalement juste une carte du mot clé à la phrase de langue:

// lang.en.js
lang = {
    greeting : "Hello"
};

// lang.fr.js
lang = {
    greeting : "Bonjour"
};

Chargez dynamiquement l'un de ces fichiers, puis il vous suffit de référencer la clé de votre carte:

document.onload = function() {
    alert(lang.greeting);
};

Il y a, bien sûr, de nombreuses autres façons de le faire, et de nombreuses façons de faire ce style, mais mieux: l'encapsulation de tout cela dans une fonction afin qu'une phrase manquante de votre "dictionnaire" puisse être gérée avec élégance, ou même faire le tout en utilisant la POO, et laissez-le gérer la dynamique y compris des fichiers, il pourrait peut-être même dessiner des sélecteurs de langue pour vous, etc.

var l = new Language('en');
l.get('greeting');
70
nickf

Il y a quelques points que vous devez garder à l'esprit lors de la conception d'un support multilingue:

1 - Séparez le code des données (c'est-à-dire ne codez pas les chaînes en dur dans vos fonctions)

2 - créez une fonction de crochet de formatage pour gérer les différences de localisation. Autoriser des chaînes formatables ("{0}") est préférable à concaténer ("Welcome to" + value), pour de nombreuses raisons:

  • dans certaines langues, un nombre est formaté comme 1.234.678,00 au lieu de 1.234.567,00
  • la pluralisation n’est souvent pas aussi simple que d’ajouter un "s" à la fin du singulier
  • les règles de grammaire sont différentes et peuvent affecter l'ordre des choses, vous devez donc autoriser l'ajout de données dynamiques après le crochet de traduction: par exemple, "Bienvenue dans {0}" se transforme en "{ 0} he youkoso " en japonais (cela se produit dans presque toutes les langues, attention).

3 - Assurez-vous que vous pouvez réellement formater les chaînes après le hook de traduction s'exécute, afin que vous puissiez réutiliser les clés.

4 - N'accrochez en aucun cas les sorties de la base de données à l'utilitaire de traduction. Si vous disposez de données multilingues, créez des tables/lignes distinctes dans votre base de données. J'ai vu des gens se tromper assez souvent sans problème (généralement pour les pays et les États/provinces sous forme).

5 - Créez des règles de pratiques de codage explicites pour la création de clés. La fonction utilitaire de mise en forme (qui ressemblera à quelque chose comme translate ("hello world") prendra une clé comme paramètre, et les touches avec de légères variations rendent la maintenance très ennuyeuse. Par exemple, vous pourriez vous retrouver avec trois clés dans l'exemple suivant: "entrez votre nom", "entrez votre nom:", "entrez votre nom:". Choisissez un format (par exemple, pas de deux-points, coupé) et détectez les écarts dans les revues de code. Ne faites pas ce filtrage par programme, car il peut déclencher de faux positifs.

6 - Gardez à l'esprit que le balisage HTML peut potentiellement être nécessaire dans le tableau de traduction (par exemple, si vous devez mettre un mot en gras dans une phrase, ou avoir des références médicales de bas de page). Testez-le longuement.

7 - Il existe plusieurs façons d'importer des chaînes de langue. Idéalement, vous devez avoir plusieurs versions d'un fichier language.lang.js, basculer entre elles avec le code côté serveur et référencer le fichier à partir du bas du fichier HTML. Tirer le fichier via AJAX est également une alternative, mais pourrait entraîner des retards. La fusion de language.js dans votre fichier de code principal n'est pas recommandée, car vous perdez les avantages de la mise en cache des fichiers.

8 - Testez avec vos langues cibles. Cela semble idiot, mais j'ai vu une fois un bug sérieux car le programmeur n'a pas pris la peine de vérifier l'existence de "é" dans la clé.

51
Leo
function Language(lang)
{
    var __construct = function() {
        if (eval('typeof ' + lang) == 'undefined')
        {
            lang = "en";
        }
        return;
    }()

    this.getStr = function(str, defaultStr) {
        var retStr = eval('eval(lang).' + str);
        if (typeof retStr != 'undefined')
        {
            return retStr;
        } else {
            if (typeof defaultStr != 'undefined')
            {
                return defaultStr;
            } else {
                return eval('en.' + str);
            }
        }
    }
}

Après l'avoir ajouté à votre page, vous pouvez l'utiliser comme ceci:

var en = {
    SelPlace:"Select this place?",
    Save:"Saved."
};

var tr = {
    SelPlace:"Burayı seçmek istiyor musunuz?"
};

var translator = new Language("en");
alert(translator.getStr("SelPlace")); // result: Select this place?
alert(translator.getStr("Save")); // result: Saved.
alert(translator.getStr("DFKASFASDFJK", "Default string for non-existent string")); // result: Default string for non-existent string

var translator = new Language("tr");
alert(translator.getStr("SelPlace")); // result: Burayı seçmek istiyor musunuz?
alert(translator.getStr("Save")); // result: Saved. (because it doesn't exist in this language, borrowed from english as default)
alert(translator.getStr("DFKASFASDFJK", "Default string for non-existent string")); // result: Default string for non-existent string

Si vous appelez la classe avec une langue que vous n'avez pas définie, l'anglais (en) sera sélectionné.

12
Nail

Je viens de trouver un bel article sur i18n en javascript:
http://24ways.org/2007/javascript-internationalisation

Bien qu'une simple recherche Google avec i18n + javascript révèle de nombreuses alternatives.

En fin de compte, cela dépend de la façon dont profond vous voulez que ce soit. Pour quelques langues, un seul fichier suffit.

Vous pouvez utiliser un framework comme Jquery , utiliser un span pour identifier le texte (avec une classe) puis utiliser l'id de chaque span pour trouver le texte correspondant dans la langue choisie.
1 ligne de Jquery, fait.

5
Berzemus

Après avoir lu les bonnes réponses de nickf et Leo, j'ai créé le style.js CommonJS suivant pour gérer toutes mes chaînes (et éventuellement, Moustache pour les formater):

var Mustache = require('mustache');

var LANGUAGE = {
    general: {
        welcome: "Welcome {{name}}!"
    }
};

function _get_string(key) {
    var parts = key.split('.');
    var result = LANGUAGE, i;
    for (i = 0; i < parts.length; ++i) {
        result = result[parts[i]];
    }
    return result;
}

module.exports = function(key, params) {
    var str = _get_string(key);
    if (!params || _.isEmpty(params)) {
        return str;
    }
    return Mustache.render(str, params);
};

Et voici comment j'obtiens une chaîne:

var L = require('language');
var the_string = L('general.welcome', {name='Joe'});
5
Tzach

Vous devriez regarder ce qui a été fait dans les composants JS classiques - prenez des choses comme Dojo, Ext, FCKEditor, TinyMCE, etc. Vous trouverez beaucoup de bonnes idées.

Habituellement, cela finit par être une sorte d'attributs que vous définissez sur les balises, puis vous remplacez le contenu de la balise par la traduction trouvée dans votre fichier de traduction, en fonction de la valeur de l'attribut.

Une chose à garder à l'esprit est l'évolution de la langue (lorsque votre code évolue, devrez-vous retraduire le tout ou non). Nous conservons les traductions dans les fichiers PO (Gnu Gettext), et nous avons un script qui transforme le fichier PO en fichiers JS prêts à l'emploi.

En plus:

  • Utilisez toujours UTF-8 - cela semble idiot, mais si vous n'êtes pas dans utf-8 depuis le début (tête HTML + encodage JS), vous serez rapidement épuisé.
  • Utilisez la chaîne anglaise comme clé de vos traductions - de cette façon, vous ne vous retrouverez pas avec des choses comme: lang.Greeting = 'Hello world' - mais lang ['Hello world'] = 'Hello world';
1
Bertrand Gorge

Pour les bundles Spring et JavaScript, il existe une solution simple: générer un tableau i18n dans un modèle (par exemple JSP) et l'utiliser en JavaScript:

JSP:

<html>
<script type="text/javascript">
    var i18n = [];
    <c:forEach var='key' items='<%=new String[]{"common.deleted","common.saved","common.enabled","common.disabled","...}%>'>
        i18n['${key}'] = '<spring:message code="${key}"/>';
    </c:forEach>
</script>
</html>

Et dans JS:

alert(i18n["common.deleted"]);

Voir aussi Resolving spring: messages in javascript for i18n internationalization

0
GKislin