diff --git a/packages/ui5-webcomponents-react-seed/README.md b/packages/ui5-webcomponents-react-seed/README.md index 52a6f524a02..e82295d3167 100644 --- a/packages/ui5-webcomponents-react-seed/README.md +++ b/packages/ui5-webcomponents-react-seed/README.md @@ -13,9 +13,9 @@ The goal of this repository is to increase the boostrap time spent on a new proj - Enviroment Variables Up & Running. -- PR Template +- Internalization Up & Running. - +- PR Template. - IE Support. @@ -78,11 +78,19 @@ Builds the app for production to the `build` folder. Used to manipulate async request, data fetching, cache and more (no redux / saga anymore). +[Tutorial Link](https://www.youtube.com/watch?v=yccbCol546c), [Random Post](https://blog.bitsrc.io/how-to-start-using-react-query-4869e3d5680d) and [Creator Official Video](https://www.youtube.com/watch?v=seU46c6Jz7E). + ### `react-helmet` Used to manpilate DOM attributes through JSX such as ``. -[Tutorial Link](https://www.youtube.com/watch?v=yccbCol546c), [Random Post](https://blog.bitsrc.io/how-to-start-using-react-query-4869e3d5680d) and [Creator Official Video](https://www.youtube.com/watch?v=seU46c6Jz7E). +### `react-i18next` + +Used to translate strings and text in the application following the Internationalization pattern. + +### `i18next-browser-languagedetector` + +Used to identify the browsers culture and change the applications text accordingly. ### `commitlint` diff --git a/packages/ui5-webcomponents-react-seed/package.json b/packages/ui5-webcomponents-react-seed/package.json index 3381713aba6..cb1cd1c5135 100644 --- a/packages/ui5-webcomponents-react-seed/package.json +++ b/packages/ui5-webcomponents-react-seed/package.json @@ -11,10 +11,13 @@ "@ui5/webcomponents-icons": "1.0.0-rc.8", "@ui5/webcomponents-react": "^0.10.0", "axios": "^0.20.0", + "i18next": "^19.7.0", + "i18next-browser-languagedetector": "^6.0.1", "jest-environment-jsdom-sixteen": "^1.0.3", "react": "^16.13.1", "react-dom": "^16.13.1", "react-helmet": "^6.1.0", + "react-i18next": "^11.7.2", "react-router-dom": "^5.2.0", "react-scripts": "3.4.3" }, diff --git a/packages/ui5-webcomponents-react-seed/public/index.html b/packages/ui5-webcomponents-react-seed/public/index.html index 04311669cad..f1bd3844809 100644 --- a/packages/ui5-webcomponents-react-seed/public/index.html +++ b/packages/ui5-webcomponents-react-seed/public/index.html @@ -1,49 +1,29 @@ - - - - - - - - - - - React App - - - -
- + + +
+ diff --git a/packages/ui5-webcomponents-react-seed/src/App.js b/packages/ui5-webcomponents-react-seed/src/App.js index a07fa9b6e52..5b7f8f14cf6 100644 --- a/packages/ui5-webcomponents-react-seed/src/App.js +++ b/packages/ui5-webcomponents-react-seed/src/App.js @@ -1,7 +1,9 @@ import React from 'react'; +import { useTranslation } from 'react-i18next'; import { BrowserRouter } from "react-router-dom"; import { Helmet } from 'react-helmet'; + import ErrorBoundary from './pages/Fallback/ErrorBoundary'; import Shell from './components/Shell/Shell'; import Routes from './routes/Routes'; @@ -9,10 +11,12 @@ import Routes from './routes/Routes'; import './App.css'; function App() { + const { t } = useTranslation(); + return ( - - + +
diff --git a/packages/ui5-webcomponents-react-seed/src/components/Shell/Shell.js b/packages/ui5-webcomponents-react-seed/src/components/Shell/Shell.js index 7f2eab699b4..0ef341827a0 100644 --- a/packages/ui5-webcomponents-react-seed/src/components/Shell/Shell.js +++ b/packages/ui5-webcomponents-react-seed/src/components/Shell/Shell.js @@ -1,4 +1,5 @@ import React from 'react'; +import { useTranslation } from 'react-i18next'; import { useHistory } from 'react-router-dom'; import { ShellBar } from '@ui5/webcomponents-react/lib/ShellBar'; @@ -13,6 +14,7 @@ const style = { }; const Shell = ({ title, ...props }) => { + const { t } = useTranslation(); const history = useHistory(); return ( @@ -20,8 +22,10 @@ const Shell = ({ title, ...props }) => { data-testid='shell-wrapper' style={style.shell} onLogoClick={() => history.push(BrowserURL.HOME)} - logo={SAP Logo} primaryTitle={title} + logo={ + {t('shell.logo.alt')} + } {...props} /> ); } diff --git a/packages/ui5-webcomponents-react-seed/src/components/Shell/__snapshots__/Shell.test.js.snap b/packages/ui5-webcomponents-react-seed/src/components/Shell/__snapshots__/Shell.test.js.snap index 0813d7f63cc..7de5ab6ed07 100644 --- a/packages/ui5-webcomponents-react-seed/src/components/Shell/__snapshots__/Shell.test.js.snap +++ b/packages/ui5-webcomponents-react-seed/src/components/Shell/__snapshots__/Shell.test.js.snap @@ -7,7 +7,7 @@ exports[`should match snapshot 1`] = ` style="position: fixed; width: 100%; z-index: 100;" > SAP Logo diff --git a/packages/ui5-webcomponents-react-seed/src/index.js b/packages/ui5-webcomponents-react-seed/src/index.js index d5652a01a25..285c424266b 100644 --- a/packages/ui5-webcomponents-react-seed/src/index.js +++ b/packages/ui5-webcomponents-react-seed/src/index.js @@ -12,6 +12,8 @@ import '@ui5/webcomponents-react/dist/Assets'; import React from 'react'; import ReactDOM from 'react-dom'; +import './util/i18n'; import App from './App'; + ReactDOM.render(, document.getElementById('root')); diff --git a/packages/ui5-webcomponents-react-seed/src/locales/en/translation.json b/packages/ui5-webcomponents-react-seed/src/locales/en/translation.json new file mode 100644 index 00000000000..ed0f7920029 --- /dev/null +++ b/packages/ui5-webcomponents-react-seed/src/locales/en/translation.json @@ -0,0 +1,12 @@ +{ + "helmet.title.app": "TodoList App", + "helmet.title.error": "Buggy Component - TodoList App", + "helmet.title.notfound": "NotFound - TodoList App", + "shell.title": "TodoList Application", + "shell.logo.alt": "SAP Logo", + "page.error.text": "Ops! There was an error in loading this page", + "page.error.alt": "Error", + "page.notfound.text": "Hmmm, we could find this URL", + "page.notfound.alt": "Not Found", + "page.fallback.reload.text": "Reload this page" +} diff --git a/packages/ui5-webcomponents-react-seed/src/locales/pt/translation.json b/packages/ui5-webcomponents-react-seed/src/locales/pt/translation.json new file mode 100644 index 00000000000..3db8eca05ed --- /dev/null +++ b/packages/ui5-webcomponents-react-seed/src/locales/pt/translation.json @@ -0,0 +1,12 @@ +{ + "helmet.title.app": "TodoList Applicação", + "helmet.title.error": "Component Bugado - TodoList App", + "helmet.title.notfound": "Não Encontrado - TodoList App", + "shell.title": "TodoList Applicação", + "shell.logo.alt": "SAP Logotipo", + "page.error.text": "Ops! Houve um erro durante o carregamento desta página", + "page.error.alt": "Erro", + "page.notfound.text": "Hmmm, não conseguimos encontrar esta página", + "page.notfound.alt": "Não Encontrado", + "page.fallback.reload.text": "Recarregar" +} diff --git a/packages/ui5-webcomponents-react-seed/src/pages/Fallback/Error.js b/packages/ui5-webcomponents-react-seed/src/pages/Fallback/Error.js index dc0503ec294..5f8e839a2e6 100644 --- a/packages/ui5-webcomponents-react-seed/src/pages/Fallback/Error.js +++ b/packages/ui5-webcomponents-react-seed/src/pages/Fallback/Error.js @@ -1,14 +1,22 @@ import React from 'react'; import { Helmet } from 'react-helmet' +import { useTranslation } from 'react-i18next'; import error from '../../assets/error.png'; import Fallback from './Fallback'; const Error = () => { + const { t } = useTranslation(); + return ( <> - - + + ); }; diff --git a/packages/ui5-webcomponents-react-seed/src/pages/Fallback/Fallback.js b/packages/ui5-webcomponents-react-seed/src/pages/Fallback/Fallback.js index dbe12c2038d..9e9e250a734 100644 --- a/packages/ui5-webcomponents-react-seed/src/pages/Fallback/Fallback.js +++ b/packages/ui5-webcomponents-react-seed/src/pages/Fallback/Fallback.js @@ -1,4 +1,5 @@ import React from 'react'; +import { useTranslation } from 'react-i18next'; import { FlexBox } from '@ui5/webcomponents-react/lib/FlexBox'; import { FlexBoxAlignItems } from '@ui5/webcomponents-react/lib/FlexBoxAlignItems'; @@ -8,15 +9,21 @@ import { FlexBoxJustifyContent } from '@ui5/webcomponents-react/lib/FlexBoxJusti import BrowserURL from '../../util/BrowserURL' const style = { + wrapper: { + width: '100%', + height: '100vh' + }, image: { width: '30%' } }; const Fallback = ({ image, altImage, text, reload }) => { + const { t } = useTranslation(); + return ( { {altImage}

{text}

{reload && ( - Reload this page + + {t('page.fallback.reload.text')} + )}
); diff --git a/packages/ui5-webcomponents-react-seed/src/pages/Fallback/NotFound.js b/packages/ui5-webcomponents-react-seed/src/pages/Fallback/NotFound.js index 8796ef8ba8f..7f56471013d 100644 --- a/packages/ui5-webcomponents-react-seed/src/pages/Fallback/NotFound.js +++ b/packages/ui5-webcomponents-react-seed/src/pages/Fallback/NotFound.js @@ -1,14 +1,21 @@ import React from 'react'; import { Helmet } from 'react-helmet'; +import { useTranslation } from 'react-i18next'; import notfound from '../../assets/notfound.png'; import Fallback from './Fallback'; const NotFound = () => { + const { t } = useTranslation(); + return ( <> - - + + ); }; diff --git a/packages/ui5-webcomponents-react-seed/src/pages/Todo/List/TodoList.js b/packages/ui5-webcomponents-react-seed/src/pages/Todo/List/TodoList.js index 61a05867dc0..175c5855512 100644 --- a/packages/ui5-webcomponents-react-seed/src/pages/Todo/List/TodoList.js +++ b/packages/ui5-webcomponents-react-seed/src/pages/Todo/List/TodoList.js @@ -11,13 +11,20 @@ export default function TodoList() { return ( <> - - history.push('/dontexist')} text='Test NotFound Page' /> + + history.push('/dontexist')} + text='Test NotFound Page' />
- history.push(BrowserURL.BUGGY)} text='Test Error Page' /> + history.push(BrowserURL.BUGGY)} + text='Test Error Page' />
- - + + ) diff --git a/packages/ui5-webcomponents-react-seed/src/util/i18n.js b/packages/ui5-webcomponents-react-seed/src/util/i18n.js new file mode 100644 index 00000000000..94c0244404b --- /dev/null +++ b/packages/ui5-webcomponents-react-seed/src/util/i18n.js @@ -0,0 +1,31 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; + +import LanguageDetector from 'i18next-browser-languagedetector'; + +import translationEN from '../locales/en/translation.json'; +import translationPT from '../locales/pt/translation.json'; + +i18n + .use(LanguageDetector) + .use(initReactI18next) + .init({ + debug: true, + keySeparator: false, + interpolation: { + escapeValue: false + }, + resources: { + en: { + translation: translationEN + }, + pt: { + translation: translationPT + } + }, + react: { + useSuspense: false + } + }); + +export default i18n; diff --git a/packages/ui5-webcomponents-react-seed/yarn.lock b/packages/ui5-webcomponents-react-seed/yarn.lock index c978d18ca40..82da5553949 100644 --- a/packages/ui5-webcomponents-react-seed/yarn.lock +++ b/packages/ui5-webcomponents-react-seed/yarn.lock @@ -1115,7 +1115,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.6": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.6": version "7.11.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== @@ -5874,6 +5874,13 @@ html-minifier-terser@^5.0.1: relateurl "^0.2.7" terser "^4.6.3" +html-parse-stringify2@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz#dc5670b7292ca158b7bc916c9a6735ac8872834a" + integrity sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o= + dependencies: + void-elements "^2.0.1" + html-webpack-plugin@4.0.0-beta.11: version "4.0.0-beta.11" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz#3059a69144b5aecef97708196ca32f9e68677715" @@ -5999,6 +6006,27 @@ hyphenate-style-name@^1.0.3: resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== +i18next-browser-languagedetector@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.0.1.tgz#83654bc87302be2a6a5a75146ffea97b4ca268cf" + integrity sha512-3H+OsNQn3FciomUU0d4zPFHsvJv4X66lBelXk9hnIDYDsveIgT7dWZ3/VvcSlpKk9lvCK770blRZ/CwHMXZqWw== + dependencies: + "@babel/runtime" "^7.5.5" + +i18next-http-backend@^1.0.18: + version "1.0.18" + resolved "https://registry.yarnpkg.com/i18next-http-backend/-/i18next-http-backend-1.0.18.tgz#ec3627c6079366665bd265054edf1fe80614089b" + integrity sha512-YPkSyqJZk8UoJTdmbisx7cPtE+04eOJlShw//O8/sj78xwlgLtqJonOyS0o+Y0ruZgfyQFMSXCZ1M4s6gQYHBw== + dependencies: + node-fetch "2.6.0" + +i18next@^19.7.0: + version "19.7.0" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-19.7.0.tgz#e637bbbf36481d34b7d5e6d3b04e1bb654bf2a26" + integrity sha512-sxZhj6u7HbEYOMx81oGwq5MiXISRBVg2wRY3n6YIbe+HtU8ydzlGzv6ErHdrRKYxATBFssVXYbc3lNZoyB4vfA== + dependencies: + "@babel/runtime" "^7.10.1" + iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -8131,6 +8159,11 @@ no-case@^3.0.3: lower-case "^2.0.1" tslib "^1.10.0" +node-fetch@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" + integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== + node-forge@0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" @@ -9918,6 +9951,14 @@ react-helmet@^6.1.0: react-fast-compare "^3.1.1" react-side-effect "^2.1.0" +react-i18next@^11.7.2: + version "11.7.2" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.7.2.tgz#b3cb94ad3b85c25e3d4802a141139d65238b976f" + integrity sha512-Djj3K3hh5Tecla2CI9rLO3TZBYGMFrGilm0JY4cLofAQONCi5TK6nVmUPKoB59n1ZffgjfgJt6zlbE9aGF6Q0Q== + dependencies: + "@babel/runtime" "^7.3.1" + html-parse-stringify2 "2.0.1" + react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -12001,6 +12042,11 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +void-elements@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" + integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= + w3c-hr-time@^1.0.1, w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"