web-dev-qa-db-fra.com

Rails: Internationalisation des chaînes Javascript?

Nous avons donc une application Rails 2.3.5 existante qui ne prend pas du tout en charge l'internationalisation. Maintenant, je connais bien le matériel Rails I18n, mais nous avons beaucoup de chaînes de sortie dans /javascripts/. Je ne suis pas un grand fan de cette approche, mais malheureusement, il est trop tard pour y remédier maintenant.

Comment pouvons-nous internationaliser les chaînes stockées dans des fichiers JS dans une application Rails? Rails ne sert même pas les fichiers JS ...

Je pense que je pourrais toujours faire en sorte que l'application Rails serve les fichiers JS, mais cela semble assez grossier. Y at-il des plugins pour faire cela?

53
Matt Rogish

Pourquoi pas quelque chose de simple comme:

<script type="text/javascript">
  window.I18n = <%= I18n.backend.send(:translations).to_json.html_safe %>
</script>

Ensuite, dans JS, vous pouvez faire des choses comme:

I18n["en-US"]["alpha"]["bravo"];

J'ai emballé le mien dans un assistant d'application.

def current_translations
  @translations ||= I18n.backend.send(:translations)
  @translations[I18n.locale].with_indifferent_access
end

Ensuite, l'appel dans application.html.erb ressemble à ceci:

<script type="text/javascript">
  window.I18n = <%= current_translations.to_json.html_safe %>
</script>

Cela vous permet d'éviter de connaître les paramètres régionaux actuels en JavaScript.

I18n["alpha"]["bravo"];

Ou

I18n.alpha.bravo;
93
Ryan Montgomery

Balibu est abandonné. Utilisez i18n-js: https://github.com/fnando/i18n-js

18
Felipe Elias Philipp

La solution de Ryan ci-dessus est parfaite, sauf que le système doit être initialisé s'il ne l'a pas déjà été.

I18n.backend.send(:init_translations) unless I18n.backend.initialized?
# now you can safely dump the translations to json
8
life_like_weeds

Pour les applications Rails 3, vous pouvez faire ceci:

Créez un fichier i18n.js.erb et ajoutez-le à votre application.js. Et ajoutez ce morceau de code Dans le fichier. 

<%
@translator = I18n.backend
@translator.load_translations
@translations ||= @translator.send(:translations)[I18n.locale][:javascript]
%>

window.I18n = <%= @translations.to_json.html_safe %>

Je vise également mes traductions pour ne pas avoir un gros fichier javascript. Mon domaine d'application est: javascript.

J'espère que ça aide quelqu'un!

6
Vince V.

Pourquoi ne pas simplement ceci dans votre fichier Javascript:

var a_message = "<%= I18n.t 'my_key' %>"

Pour que cela fonctionne, vous devez ajouter .erb à l'extension de votre fichier Javascript.

Vous pourriez également avoir besoin d’ajouter la ligne suivante en haut de votre fichier Javascript si vous n’utilisez pas Ruby> = 2.0.

<%# encoding: utf-8 %>

Voir le dernier commentaire de la réponse acceptée dans ce fil pour plus d’informations: Problèmes d’encodage dans les fichiers javascript à l’aide de Rails Asset Pipeline

5
Dany Marcoux

Une autre option qui pourrait être utile:

En supposant que vous ayez un modèle Language (slug) contenant toutes les langues disponibles . Il gère les cas où il manque une traduction (elle est remplacée par la version locale par défaut).

assets/javascript/i18n.js.erb

<%
@translator = I18n.backend
@translator.load_translations

translations = {}
Language.all.each do |l|
    translations[l.slug] = @translator.send(:translations)[l.slug.to_sym]
end

@translations = translations

%>
window.I18n = <%= @translations.to_json.html_safe %>

window.I18n.t = function(key){
    if(window.I18n[current_locale]){
        el = eval("I18n['"+current_locale+"']." + key);
    }
    if(window.I18n[default_locale] && typeof(el) == 'undefined'){
        el = eval("I18n['"+default_locale+"']." + key);
    }
    if(typeof(el) == 'undefined'){
        el = key;
    }
    return el;
};

views/layout/application.html.erb

...
<%= javascript_tag "var current_locale = '#{I18n.locale.to_s}';" %>
<%= javascript_tag "var default_locale = '#{I18n.default_locale}';" %>
...

En votre code javascript, vous pouvez traduire comme ceci:

// current_locale:fr , default_locale:en

// existing translation (in french) 
I18n.t('message.hello_world'); // => Bonjour le monde

// non-existing translation (in french) but existing in english 
I18n.t('message.hello_this_world'); // => Hello this world

// non-existing translation (french & english) 
I18n.t('message.hello_this_new_world'); // => message.hello_this_new_world

J'espère que ça aide!

2
melalj

Babilu est un plugin Rails qui le fait pour vous.

2
sblom

La solution Ryan est géniale . Mais pour ne pas inclure le fichier entier, vous devez utiliser: @translations[I18n.locale].with_indifferent_access["alpha"] Au lieu de I18n.backend.send(:translations)["alpha"]

1
macler

I18n-js fonctionne très bien pour moi et je le recommande. Si vous utilisez sa branche rewrite , le plug-in comprendra un fichier /assets/i18n/filtered.js qui affiche exactement les réponses données par @ ryan-montgomery, sans rien faire vous-même manuellement.

De cette façon, vous pouvez utiliser les mêmes traductions sur le backend Avec Rails helpers t(:key) et utiliser I18n.t('key') en Javascript sur le frontend. 

0
robbie613

Pour des applications telles que celle que vous avez décrite "ne supportant pas l'internationalisation du tout" et "il est trop tard pour y remédier", j'ai écrit une approche très rapide: le plugin jQuery Quick-i18n: https://github.com/ katio/Quick-i18n demo (et comment l'utiliser): http://johannpaul.net/Quick-i18n/

0
Johann Echavarria