-
-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add multi-language capability to blip with react-i18next #468
Conversation
Procedure: - surround all text to be translated with __() - npm run update-translations will update the .po files in translations/ - Use appropriate software to add translations - npm run build-translations will transform the .po files into .json Then the webpack script takes care of generating a separate index.[xx].html and bundle.[xx].js for each language in dist. For now, the server only serves index.en.html
Set default language to French (pending a per-user setting) and add translations for the navbar
- Move the loading of translations out of dependencies/i18n - Change languages.json from [languageCode] to {languageCode: language} - Move the language setting out of bootstrap.js and into core/language - Add language selection in userprofile to change language - Language selection is only client-side, not yet stored server-side
If the user hasn't yet set a language in their settings, use the browser's language instead.
Not yet using react-i18next. i18next allows to keep things minimal, react-i18next would introduce decorators and extracting t from props. I am still using i18n-extract to extract translations, next step is using i18next-parser
- Sort translation keys in the JSON - Translate the front page - Remove unneeded dependencies - Fix stuff
7fc2bd6
to
162806f
Compare
The weekly/trends chart have also been updated from "MMM D" to "D MMM" in French
0f366c1
to
1134b52
Compare
Translations are now extracted from blip's two submodules. That way they don't need the extra-tooling, only i18next as a dependency. Furthermore, they can prefix their translatable strings with 'viz|' or 'tideline|' to use a different namespace and separate their translations from blip's translation.
app/components/chart/trends.js
Outdated
@@ -35,6 +36,7 @@ const TrendsContainer = viz.containers.TrendsContainer; | |||
const reshapeBgClassesToBgBounds = viz.utils.reshapeBgClassesToBgBounds; | |||
const Loader = viz.components.Loader; | |||
|
|||
@translate() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we currently don't have any decorator patterns in the codebase, I'd be hesitant to add it right now. I'm not opposed to the idea, but perhaps I'd like @cbwebdevelopment's opinion as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I actually do like decorator patterns (I've used them on past projects), but for consistency with the rest of the codebase at this point, I think we should hold off on introducing them, and use the HOC approach used everywhere else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the PR by removing the decorator pattern. I also marked the rest of blip for translation (all tests passing) in the language
branch of my fork, ready to make another PR.
eb51455
to
11914c7
Compare
Closing this proof-of-concept PR, which is superseded by #473 |
Related issue: #449
As a proof of concept, the front page, the navbar and the account settings page have translations added for French. Language can be changed in the account settings page.
The workflow changes are described below:
Extracting translation keys from code
Just run
npm run update-translations
. It uses i18next-parser under the hood.The json files localted in
locales/xx
are updated.Translating components
There are two steps: wrapping the component with
translate(namespace?, options?)()
fromreact-i18next
, and extractingt
fromthis.props
.When using
React.createClass
:When using the ES6 way of creating components,
translate
can be used as a decorator:The default namespace is unchanged and is
'translation'
.An alternative to using the
translate
decorator on the component is wrapping the rendered content with theI18n
component, as seen here.Warning: When trying to access member function of decorated components from the outside, you will need to 'unwrap' the component.
For that you need to first add
withRef
as an parameter totranslate
:With that is it possible to access
hideDropdown
fromapp.js
:Interpolation, templated strings
Something like:
Would become:
Html mixed with text
Something like:
Would become:
The key as interpreted by i18next would be
html.hello-noticiation
, and the default value would be this:Hello, <1>{{name}}</1>. You have <3>{{count: messages.length}}</3> notifications.
. As such, the content of the html doesn't appear in the translation and is not editable by the translator. Moreover, the html can be changed without changing the key.Translating submodules
@tidepool/viz
andtideline
can add tranlations by addingi18next
as a dependency, and usingi18next.t()
, blip is already configured to extract translatable strings from them.They can prefix their translatable strings with
tideline|
orviz|
to use separate namespaces from blip.Considerations
It is possible to implement lazy loading of translations with i18next-xhr-backend with a change in webpack's config file, however locize is to be used in the future, with translations stored in the cloud.
Only a small part of the application has been translated. The idea is, if this PR is accepted and multi-language functionnality added to tidepool, to make a pull request to translate every component, maybe another to use keys as translation strings, and another to translate
viz
andtideline
. Each of these further PRs can be subject to debate (amount of code changed, implementation, possible undetected errors when mass-updating the app...) and this is why I feel that an incremental process is better, rather than a monolithic PR with massive code changes.