Can anyone give me best practice or just an idea how to work with i18n components? Can be the locale passed to all the components?
Right now I'm passing locale with props and setting there
I18n.locale = this.props.localein render, before all the jsx constructions.
That's a good question. I'm also wondering how to.
I am using i18njs to do this for now and then just doing I18n.t('my.key.here') to get strings out.
That's what I'm also doing currently, but it doesn't look right. Hopefully to find out better approach soon.
We're using Yahoo's react_intl and merging in its expected properties into every component manually.
Over-simplified, it looks something like this:
<%
desired_locale_context = { locales: 'en-US', messages: { 'key': 'value', 'key2': I18n.t('rails.key2') } }
other_props = { x: true, y: 2 }
component_props = desired_locale_context.merge(other_props)
%>
<%= react_component 'MyComponent', component_props %>
Would be nice if there was a way to have them merged in by default.
How do you pass current locale to the nested components?
I'm passing as a normal props and setting them to the state. Isn't it better to set locale as a global state property?
The particular library I'm using passes them down automatically (or the children fetch from their parents).
For other libraries, not sure what the best practice is for this sort of state. If you're using a Flux-like architecture, a LocaleStore might make sense. I'm not sure exactly what you're describing but the docs do warn against using props to set state. https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html
We have been using i18n-js quite successfully with react-rails. It's very nice being able to reuse translations from your rails app and it works well.
We only had to do a little extra setup work to make it work properly with server-side prerendering. You can find our setup here https://gist.github.com/jhilden/44378421ad54e617b900
Thanks for the all the examples!
If anyone is coming to this from google and wanted a different way to implement this.
This is what I did and is working great. I found this solution to be the most simple.
gem "i18n-js"
yarn add i18n-js
Enabled webpacker erb
Changed server_rendering.js to server_rendering.js.erb
Changed application.js to application.js.erb
Added these two lines in both files
import I18n from "i18n-js";
I18n.translations = <%= I18n::JS.translations.to_json %>;
Now in any of my components.
import React from "react"
import PropTypes from "prop-types"
import I18n from 'i18n-js';
class HelloWorld extends React.Component {
render () {
return (
<React.Fragment>
<div>{I18n.t("greeting")}</div>
</React.Fragment>
);
}
}
export default HelloWorld;
Hi @ericraio Nice one! This is going in the readme 馃帀 Very nice.
Hi @ericraio Nice one! This is going in the readme 馃帀 Very nice.
Awesome! One gotcha is to delete the generated comment, it has erb which causes an error after changing the file to erb.
import I18n from "i18n-js";
@ericraio import is not working for me and failing with "Cannot find module 'i18n-js'". I am using i18n-js 3.3.0 with React 16.5.2.
Hi @ericraio, thanks for the solution.
In my case all is good, but if I change default locale to something else rather than "en", it still defaults to EN. Any idea what can be wrong?
If you need default locale from rails in many components we use this approach:
// config/initializers/locale.rb
I18n.load_path += Dir[Rails.root.join('lib', 'locale', '*.{rb,yml}')]
I18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
I18n.default_locale = :ru
I18n.available_locales = %i[ru en]
class I18nComponentMount < React::Rails::ComponentMount
def react_component(name, props = {}, options = {}, &block)
props[:i18n] = {
locale: I18n.locale,
default_locale: I18n.default_locale,
available_locales: I18n.available_locales
}
super
end
end
Rails.application.configure do
config.react.view_helper_implementation = I18nComponentMount
end
After this every components has locales props and then use ericraio code.
Most helpful comment
If anyone is coming to this from google and wanted a different way to implement this.
This is what I did and is working great. I found this solution to be the most simple.
Enabled webpacker erb
Changed
server_rendering.jstoserver_rendering.js.erbChanged
application.jstoapplication.js.erbAdded these two lines in both files
Now in any of my components.