diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f436c8c..be3759ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ way to update this template, but currently, we follow a pattern: ## Upcoming version 2019-XX-XX +- [change] Default to English translation if the translation key is missing. After this update, new translation keys will not be added to other translation files with English default texts. We keep providing translations in our supported languages but they might not be up to date all the time. This means if you want to update your translations beforehand or use your own translations file, you can use [translation CLI]((https://github.com/sharetribe/flex-template-web/blob/master/docs/translations.md#managing-translations)) to check if there are translations missing. + [#1005](https://github.com/sharetribe/flex-template-web/pull/1005) - [change] Remove `origin` parameter from `default-location-searches.js` [#1003](https://github.com/sharetribe/flex-template-web/pull/1003) - [add] Limit location autocomplete by adding an optional country parameter to geocoding call in diff --git a/docs/translations.md b/docs/translations.md index 1a5ad6d7..b0425983 100644 --- a/docs/translations.md +++ b/docs/translations.md @@ -1,8 +1,8 @@ # Translations The Flex Template for Web supports having a single language for the UI. Supported languages are -English and French, English being used by default. For information about changing the language, see -[here](#changing-the-language). +English, French and Spanish, English being used by default. For information about changing the +language, see [here](#changing-the-language). We are using the [React Intl](https://github.com/yahoo/react-intl) library to translate UI texts and to format dates, numbers, and money values. @@ -134,6 +134,8 @@ More information about adding static content to the application can be found fro If you want the template to use a language that is not supported by default a new translation file needs to be added and the messages in it need to be translated: +### Creating a new translation file + 1. Copy the default [src/translations/en.json](../src/translations/en.json) English translations file into some other file, for example `it.json` for Italian. @@ -142,26 +144,39 @@ needs to be added and the messages in it need to be translated: > Note: we already have a few other language files available in > [translations directory](../src/translations/) for you to start customizing translations. +### Changing the translations used in FTW + Once you have the translations file in place: -3. In [src/config.js](../src/config.js), change the `locale` variable value to match the new locale +1. In [src/config.js](../src/config.js), change the `locale` variable value to match the new locale (the name of the new translations file, without the extension), for example: ```js const locale = 'it'; ``` -4. In [src/app.js](../src/app.js), change the translation imports to point to the correct - `react-intl` locale and the new translations file you created, for example: +2. In [src/app.js](../src/app.js), change the React Intl import to point to the correct `react-intl` + locale, for example: ```js import localeData from 'react-intl/locale-data/it'; -import messages from './translations/it.json'; -// If you are using a non-english locale with moment library, -// you should also import time specific formatting rules for that locale +``` + +3. If you are using a non-english locale with moment library, you should also import time specific + formatting rules for that locale: + +```js import 'moment/locale/it'; ``` +4. Point `messagesInLocale` to correct .json file, for example: + +```js +import messagesInLocale from './translations/it.json'; +``` + +### Changing the translation used in tests + Also, in case you will translate the application and develop it forward it is wise to change the translations file that the tests use. Normally tests are language agnostic as they use translation keys as values. However, when adding new translations you can end up with missing translation keys diff --git a/src/app.js b/src/app.js index a3cffc8d..71497cf4 100644 --- a/src/app.js +++ b/src/app.js @@ -9,6 +9,7 @@ import 'react-dates/initialize'; import Helmet from 'react-helmet'; import { BrowserRouter, StaticRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; +import difference from 'lodash/difference'; import mapValues from 'lodash/mapValues'; import moment from 'moment'; import { IntlProvider, addLocaleData } from 'react-intl'; @@ -17,16 +18,50 @@ import routeConfiguration from './routeConfiguration'; import Routes from './Routes'; import config from './config'; -// If you want to change the language, Change the imports to the match -// the wanted locale. -// -// Remember to also change the language in the config.js file. +// Flex template application uses English translations as default. +import defaultMessages from './translations/en.json'; + +// If you want to change the language, change the imports to match the wanted locale: +// 1) Change the language in the config.js file! +// 2) Import correct locale rules for React Intl library +// 3) Import correct locale rules for Moment library +// 4) Use the `messagesInLocale` import to add the correct translation file. + +// Step 2: +// Import locale rules for React Intl library import localeData from 'react-intl/locale-data/en'; -import messages from './translations/en.json'; + +// Step 3: // If you are using a non-english locale with moment library, // you should also import time specific formatting rules for that locale // e.g. for French: import 'moment/locale/fr'; +// Step 4: +// If you are using a non-english locale, point `messagesInLocale` to correct .json file +import messagesInLocale from './translations/fr.json'; + +// If translation key is missing from `messagesInLocale` (e.g. fr.json), +// corresponding key will be added to messages from `defaultMessages` (en.json) +// to prevent missing translation key errors. +const addMissingTranslations = (sourceLangTranslations, targetLangTranslations) => { + const sourceKeys = Object.keys(sourceLangTranslations); + const targetKeys = Object.keys(targetLangTranslations); + const missingKeys = difference(sourceKeys, targetKeys); + + const addMissingTranslation = (translations, missingKey) => ({ + ...translations, + [missingKey]: sourceLangTranslations[missingKey], + }); + + return missingKeys.reduce(addMissingTranslation, targetLangTranslations); +}; + +const isDefaultLanguageInUse = config.locale === 'en'; + +const messages = isDefaultLanguageInUse + ? defaultMessages + : addMissingTranslations(defaultMessages, messagesInLocale); + const isTestEnv = process.env.NODE_ENV === 'test'; // Locale should not affect the tests. We ensure this by providing