I have added to my project react-rails
gem and I want to use for translated components.
I cannot put in the precompiled assets erb
templates, but still I am trying to create components, make them available in all the project and then use them in some partial with some translation.
Working Scenario
# app/view/example/_react_component.coffee.erb
DOM = React.DOM
FormInput = React.createClass
displayName: "FormInput"
render: ->
DOM.div
className: 'row control-group'
DOM.div
className: 'form-group col-xs-12 floating-label-form-group controls'
DOM.label
htmlFor: @props.id
@props.label
DOM.input
id: @props.id
className: 'form-control'
placeholder: @props.placeholder
type: @props.type
DOM.p
className: 'help-block text-danger'
formInput = React.createFactory(FormInput)
window.ValidationFormInput = React.createClass
displayName: "ValidationFormInput"
getInitialState: ->
{ }
render: ->
formInput
id: "<%= t('validation_form.id') %>"
label: "<%= t('validation_form.label') %>"
placeholder: "<%= t('validation_form.placeholder') %>"
type: 'text'
validationFormInput = React.createFactory(ValidationFormInput)
# app/view/example/index.html.erb
<%= react_component('ValidationFormInput', {}, {class: "container"}) %>
Desired Scenario (not working)
# app/assets/javascripts/components/form_input.coffee
DOM = React.DOM
FormInput = React.createClass
displayName: "FormInput"
render: ->
DOM.div
className: 'row control-group'
DOM.div
className: 'form-group col-xs-12 floating-label-form-group controls'
DOM.label
htmlFor: @props.id
@props.label
DOM.input
id: @props.id
className: 'form-control'
placeholder: @props.placeholder
type: @props.type
DOM.p
className: 'help-block text-danger'
formInput = React.createFactory(FormInput)
# app/view/example/_react_component.coffee.erb
window.ValidationFormInput = React.createClass
displayName: "ValidationFormInput"
getInitialState: ->
{ }
render: ->
formInput
id: "<%= t('validation_form.id') %>"
label: "<%= t('validation_form.label') %>"
placeholder: "<%= t('validation_form.placeholder') %>"
type: 'text'
validationFormInput = React.createFactory(ValidationFormInput)
# app/view/example/index.html.erb
<%= react_component('ValidationFormInput', {}, {class: "container"}) %>
I guess that the issue is related to the scope of the definition of my component, but I cannot figure out how to make the component available for any partial.
Thank you in advance
Edit
In order to make the translations available, I found the gem I18n-js
. After installing, I can easily run a rake task to create a js version of my config/locales/*
translations
Excellent question.
There are a few ways to do this.
1- Usually, this is not just a question about how to pass data from Rails to React but rather how to generally pass data to Javascript. You can store the data in a meta
in the header and access it from Javascript. This way you can still have your JS compressed and fast. (Instead of js.erb etc)
2- Passing all the translations to the react component. Basically, you can pass arguments to the react component, one of which is the translations. If it's a few translations, it's fine but if your list grows, the load would be heavy on your page.
3- Make your own Javascript translator. Here's a CoffeeScript example that I have created; make sure to add it in your assets' list before the other files.
In my code, I'm pulling the locale from meta
(as you can see in the code). Feel free to edit this.
class Translator
@en = {
internet_connection_lost: "Your internet connection has been lost"
attempting_to_reconnect: "Attempting to reconnect!"
failed_to_reconnect: "Failed to reconnect..."
connection_success: "Connected"
reconnecting: "Reconnecting..."
bid_received: "Bid received. New balance $$bid_balance$$"
}
@ar = {
internet_connection_lost: "لقد فقدت الاتصال بالإنترنت"
attempting_to_reconnect: "نحاول إعادة الاتصال!"
failed_to_reconnect: "لم تنجح إعادة الاتصال بالشبكة..."
connection_success: "متصل بشبكة الإنترنت"
reconnecting: "إعادة الاتصال جارية..."
bid_received: "تم تلقي العرض. رصيد جديد $$bid_balance$$"
}
@get_translations: (locale) ->
switch (locale)
when 'en'
@en
when 'ar'
@ar
@translate: (val, interpolation) ->
# get locale from meta
locale = $("meta[name='locale']").attr("content") || "en"
translation = Translator.get_translations(locale)[val]
if interpolation
console.log "#{JSON.stringify(interpolation)}"
for k,v of interpolation
console.log "#{translation} : #{k} : #{v}"
translation = translation.replace(k, v)
return translation
window.Translator = Translator
And this is how you can use the Translator
message = Translator.translate(
"bid_received", { "$$bid_balance$$": 10 }
)