From 675ee980ee2c4c789e52d38553f751bb219d1270 Mon Sep 17 00:00:00 2001 From: Priscila Oliveira Date: Thu, 23 Apr 2020 08:20:41 +0200 Subject: [PATCH] feat(lng): Added change language on the fly (#456) * feat(lng): added change language on the fly * fixed dropdown * applied feedbacks * added translation * updated bundlesize * fixed error * updated snaps * added french language * added language in storage * updated styles * fixed tests --- i18n/config.ts | 45 ++- i18n/translations/de-DE.json | 12 +- i18n/translations/en-US.json | 12 +- i18n/translations/es-ES.json | 12 +- i18n/translations/fr-FR.json | 12 +- i18n/translations/pt-BR.json | 14 +- i18n/translations/zh-CN.json | 12 +- package.json | 2 +- src/App/__snapshots__/App.test.tsx.snap | 358 ++++++++++++------ src/App/load-dayjs-locale.ts | 3 +- src/components/Header/HeaderRight.tsx | 2 + .../Header/__snapshots__/Header.test.tsx.snap | 178 +++++++-- src/components/Icon/Icon.tsx | 6 + src/components/Icon/img/france.svg | 1 + src/components/Icon/img/usa.svg | 1 + .../LanguageSwitch/LanguageSwitch.tsx | 204 ++++++++++ src/components/LanguageSwitch/index.ts | 1 + src/design-tokens/ThemeContext.ts | 3 + src/design-tokens/ThemeProvider.tsx | 18 +- src/muiComponents/MenuItem/MenuItem.tsx | 7 +- src/utils/package.ts | 4 +- 21 files changed, 731 insertions(+), 176 deletions(-) create mode 100644 src/components/Icon/img/france.svg create mode 100644 src/components/Icon/img/usa.svg create mode 100644 src/components/LanguageSwitch/LanguageSwitch.tsx create mode 100644 src/components/LanguageSwitch/index.ts diff --git a/i18n/config.ts b/i18n/config.ts index 7466631..370500d 100644 --- a/i18n/config.ts +++ b/i18n/config.ts @@ -8,6 +8,29 @@ import translationDE from './translations/de-DE.json'; import translationFR from './translations/fr-FR.json'; import translationCN from './translations/zh-CN.json'; +const languages = { + 'en-US': { + translation: translationEN, + }, + 'pt-BR': { + translation: translationPT, + }, + 'es-ES': { + translation: translationES, + }, + 'de-DE': { + translation: translationDE, + }, + 'fr-FR': { + translation: translationFR, + }, + 'zh-CN': { + translation: translationCN, + }, +}; + +type Language = keyof typeof languages; + i18n // pass the i18n instance to react-i18next. .use(initReactI18next) @@ -19,26 +42,7 @@ i18n fallbackLng: 'en-US', whitelist: ['en-US', 'pt-BR', 'es-ES', 'de-DE', 'fr-FR', 'zh-CN'], load: 'currentOnly', - resources: { - 'en-US': { - translation: translationEN, - }, - 'pt-BR': { - translation: translationPT, - }, - 'es-ES': { - translation: translationES, - }, - 'de-DE': { - translation: translationDE, - }, - 'fr-FR': { - translation: translationFR, - }, - 'zh-CN': { - translation: translationCN, - }, - }, + resources: languages, debug: false, interpolation: { escapeValue: false, // react already safes from xss @@ -46,3 +50,4 @@ i18n }); export default i18n; +export { Language }; diff --git a/i18n/translations/de-DE.json b/i18n/translations/de-DE.json index 8598dbe..3645085 100644 --- a/i18n/translations/de-DE.json +++ b/i18n/translations/de-DE.json @@ -135,5 +135,15 @@ "app-context-not-correct-used": "Der App-Kontext wurde nicht korrekt verwendet", "theme-context-not-correct-used": "Der Theme-Kontext wurde nicht korrekt verwendet", "package-meta-is-required-at-detail-context": "packageMeta wird bei DetailContext benötigt" - } + }, + "lng": { + "english": "Englisch", + "portuguese": "Portugiesisch", + "spanish": "Spanisch", + "german": "Deutsch", + "chinese": "Chinesisch", + "french": "Französisch" + }, + "help-to-translate": "Hilfe beim Übersetzen", + "change-language": "Sprache ändern" } diff --git a/i18n/translations/en-US.json b/i18n/translations/en-US.json index a4be29a..657861a 100644 --- a/i18n/translations/en-US.json +++ b/i18n/translations/en-US.json @@ -135,5 +135,15 @@ "app-context-not-correct-used": "The app context was not used correctly", "theme-context-not-correct-used": "The theme context was not used correctly", "package-meta-is-required-at-detail-context": "packageMeta is required at DetailContext" - } + }, + "lng": { + "english": "English", + "portuguese": "Portuguese", + "spanish": "Spanish", + "german": "German", + "chinese": "Chinese", + "french": "French" + }, + "help-to-translate": "Help to translate", + "change-language": "Change language" } \ No newline at end of file diff --git a/i18n/translations/es-ES.json b/i18n/translations/es-ES.json index 204664d..62e42d1 100644 --- a/i18n/translations/es-ES.json +++ b/i18n/translations/es-ES.json @@ -135,5 +135,15 @@ "app-context-not-correct-used": "El contexto de la aplicación no fue correctamente usado", "theme-context-not-correct-used": "El contexto del tema no fue correctamente usado", "package-meta-is-required-at-detail-context": "packageMeta es requerido en DetailContext" - } + }, + "lng": { + "english": "Inglés", + "portuguese": "Portugués", + "spanish": "Español", + "german": "Alemán", + "chinese": "Chino", + "french": "francés" + }, + "help-to-translate": "Ayuda a traducir", + "change-language": "Cambiar idioma" } diff --git a/i18n/translations/fr-FR.json b/i18n/translations/fr-FR.json index e749eeb..26376d0 100644 --- a/i18n/translations/fr-FR.json +++ b/i18n/translations/fr-FR.json @@ -135,5 +135,15 @@ "app-context-not-correct-used": "Le contexte de l'application n'a pas été utilisé correctement", "theme-context-not-correct-used": "Le contexte du thème n'a pas été utilisé correctement", "package-meta-is-required-at-detail-context": "packageMeta est obligatoire à DetailContext" - } + }, + "lng": { + "english": "Anglaise", + "portuguese": "Portugaise", + "spanish": "Espagnol", + "german": "Allemande", + "chinese": "Chinoise", + "french": "Française" + }, + "help-to-translate": "Aide à traduire", + "change-language": "Changer la langue" } \ No newline at end of file diff --git a/i18n/translations/pt-BR.json b/i18n/translations/pt-BR.json index f3a8cf9..8dabcc0 100644 --- a/i18n/translations/pt-BR.json +++ b/i18n/translations/pt-BR.json @@ -114,7 +114,7 @@ } }, "footer": { - "powered-by": "Distribuído por", + "powered-by": "Feito por", "made-with-love-on": "Feito com amor <0>♥ no(a)" }, "button": { @@ -135,5 +135,15 @@ "app-context-not-correct-used": "O contexto do aplicativo não foi usado corretamente", "theme-context-not-correct-used": "O contexto do tema não foi usado corretamente", "package-meta-is-required-at-detail-context": "packageMeta é requerido em DetailContext" - } + }, + "lng": { + "english": "Inglês", + "portuguese": "Português", + "spanish": "Espanhol", + "german": "Alemão", + "chinese": "Chinês", + "french": "Francês" + }, + "help-to-translate": "Ajude a traduzir", + "change-language": "Mudar idioma" } \ No newline at end of file diff --git a/i18n/translations/zh-CN.json b/i18n/translations/zh-CN.json index d2dd3d2..800436a 100644 --- a/i18n/translations/zh-CN.json +++ b/i18n/translations/zh-CN.json @@ -134,5 +134,15 @@ }, "app-context-not-correct-used": "The app context was not correct used", "package-meta-is-required-at-detail-context": "packageMeta is required at DetailContext" - } + }, + "lng": { + "english": "英語", + "portuguese": "葡萄牙語", + "spanish": "西班牙文", + "german": "德語", + "chinese": "中文", + "french": "法國人" + }, + "help-to-translate": "幫助翻譯", + "change-language": "改變語言" } \ No newline at end of file diff --git a/package.json b/package.json index fd76d55..68e4a2b 100644 --- a/package.json +++ b/package.json @@ -140,7 +140,7 @@ "bundlesize": [ { "path": "./static/vendors.*.js", - "maxSize": "200 kB" + "maxSize": "210 kB" }, { "path": "./static/main.*.js", diff --git a/src/App/__snapshots__/App.test.tsx.snap b/src/App/__snapshots__/App.test.tsx.snap index d77e7be..60a8799 100644 --- a/src/App/__snapshots__/App.test.tsx.snap +++ b/src/App/__snapshots__/App.test.tsx.snap @@ -1,11 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[` should display the Header component 1`] = ` -.emotion-81 { +.emotion-85 { background-color: #fff; } -.emotion-24 { +.emotion-28 { background-color: #4b5e40; color: #fff; min-height: 60px; @@ -20,29 +20,29 @@ exports[` should display the Header component 1`] = ` } @media (min-width:768px) { - .emotion-24 .emotion-13 { + .emotion-28 .emotion-13 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } - .emotion-24 .emotion-17 { + .emotion-28 .emotion-17 { display: none; } - .emotion-24 .e1jf5lit4 { + .emotion-28 .e1jf5lit4 { display: none; } } @media (min-width:1024px) { - .emotion-24 .emotion-23 { + .emotion-28 .emotion-27 { padding: 0 20px; } @media (min-width:1275px) { - .emotion-24 .emotion-23 { + .emotion-28 .emotion-27 { max-width: 1240px; width: 100%; margin: 0 auto; @@ -50,7 +50,7 @@ exports[` should display the Header component 1`] = ` } } -.emotion-22 { +.emotion-26 { -webkit-box-pack: justify; -webkit-justify-content: space-between; -ms-flex-pack: justify; @@ -128,7 +128,7 @@ exports[` should display the Header component 1`] = ` overflow-y: auto; } -.emotion-20 { +.emotion-24 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -140,12 +140,32 @@ exports[` should display the Header component 1`] = ` display: block; } +.emotion-20 { + display: none; +} + +@media screen and (min-width:768px) { + .emotion-20 { + display: inline-block; + } +} + .emotion-18 { + display: none; +} + +@media screen and (min-width:768px) { + .emotion-18 { + display: inline-block; + } +} + +.emotion-22 { color: #fff; } @media screen and (min-width:1240px) { - .emotion-36 { + .emotion-40 { max-width: 1240px; width: 100%; margin-left: auto; @@ -153,7 +173,7 @@ exports[` should display the Header component 1`] = ` } } -.emotion-79 { +.emotion-83 { background: #f9f9f9; border-top: 1px solid #e3e3e3; color: #999999; @@ -161,7 +181,7 @@ exports[` should display the Header component 1`] = ` padding: 20px; } -.emotion-77 { +.emotion-81 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -178,7 +198,7 @@ exports[` should display the Header component 1`] = ` } @media (min-width:768px) { - .emotion-77 { + .emotion-81 { min-width: 400px; max-width: 800px; margin: auto; @@ -190,12 +210,12 @@ exports[` should display the Header component 1`] = ` } @media (min-width:1024px) { - .emotion-77 { + .emotion-81 { max-width: 1240px; } } -.emotion-68 { +.emotion-72 { -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; @@ -204,7 +224,7 @@ exports[` should display the Header component 1`] = ` } @media (min-width:768px) { - .emotion-68 { + .emotion-72 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -212,21 +232,21 @@ exports[` should display the Header component 1`] = ` } } -.emotion-38 { +.emotion-42 { color: #e25555; padding: 0 5px; } -.emotion-66 { +.emotion-70 { position: relative; height: 18px; } -.emotion-66:hover .emotion-65 { +.emotion-70:hover .emotion-69 { visibility: visible; } -.emotion-41 { +.emotion-45 { box-sizing: initial; display: inline-block; cursor: default; @@ -235,7 +255,7 @@ exports[` should display the Header component 1`] = ` padding: 0 10px; } -.emotion-64 { +.emotion-68 { position: absolute; background: #d3dddd; padding: 1px 4px; @@ -253,7 +273,7 @@ exports[` should display the Header component 1`] = ` top: -2px; } -.emotion-64:before { +.emotion-68:before { content: ''; position: absolute; top: 29%; @@ -266,7 +286,7 @@ exports[` should display the Header component 1`] = ` transform: rotate(90deg); } -.emotion-44 { +.emotion-48 { box-sizing: initial; display: inline-block; cursor: default; @@ -275,7 +295,7 @@ exports[` should display the Header component 1`] = ` padding: 0 5px; } -.emotion-75 { +.emotion-79 { -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; @@ -288,7 +308,7 @@ exports[` should display the Header component 1`] = ` } @media (min-width:768px) { - .emotion-75 { + .emotion-79 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -296,7 +316,7 @@ exports[` should display the Header component 1`] = ` } } -.emotion-73 { +.emotion-77 { box-sizing: initial; display: inline-block; cursor: pointer; @@ -305,12 +325,12 @@ exports[` should display the Header component 1`] = ` padding: 0 5px; } -.emotion-70 { +.emotion-74 { width: 100%; height: auto; } -.emotion-34 { +.emotion-38 { -webkit-transform: translate(-50%,-50%); -ms-transform: translate(-50%,-50%); transform: translate(-50%,-50%); @@ -319,14 +339,14 @@ exports[` should display the Header component 1`] = ` position: absolute; } -.emotion-28 { +.emotion-32 { margin: 0 0 30px 0; border-radius: 25px; box-shadow: 0 10px 20px 0 rgba(69,58,100,0.2); background: #f7f8f6; } -.emotion-26 { +.emotion-30 { display: inline-block; vertical-align: middle; box-sizing: border-box; @@ -338,7 +358,7 @@ exports[` should display the Header component 1`] = ` height: 90px; } -.emotion-32 { +.emotion-36 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -353,19 +373,19 @@ exports[` should display the Header component 1`] = ` justify-content: center; } -.emotion-30 { +.emotion-34 { color: #4b5e40; }
should display the Header component 1`] = `
+
+ +
should display the Header component 1`] = `
-
-
-
+
+
+
@@ -610,26 +675,26 @@ exports[` should display the Header component 1`] = `
Made with on Earth @@ -639,10 +704,10 @@ exports[` should display the Header component 1`] = ` /> Spain @@ -652,7 +717,7 @@ exports[` should display the Header component 1`] = ` /> Nicaragua @@ -662,7 +727,7 @@ exports[` should display the Header component 1`] = ` /> India @@ -672,7 +737,7 @@ exports[` should display the Header component 1`] = ` /> Brazil @@ -682,7 +747,7 @@ exports[` should display the Header component 1`] = ` /> China @@ -692,7 +757,7 @@ exports[` should display the Header component 1`] = ` /> Austria @@ -702,7 +767,7 @@ exports[` should display the Header component 1`] = ` /> Germany @@ -715,16 +780,16 @@ exports[` should display the Header component 1`] = `
Powered by Verdaccio @@ -736,11 +801,11 @@ exports[` should display the Header component 1`] = ` `; exports[` should display the Loading component at the beginning 1`] = ` -.emotion-71 { +.emotion-75 { background-color: #fff; } -.emotion-24 { +.emotion-28 { background-color: #4b5e40; color: #fff; min-height: 60px; @@ -755,29 +820,29 @@ exports[` should display the Loading component at the beginning 1`] = ` } @media (min-width:768px) { - .emotion-24 .emotion-13 { + .emotion-28 .emotion-13 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } - .emotion-24 .emotion-17 { + .emotion-28 .emotion-17 { display: none; } - .emotion-24 .e1jf5lit4 { + .emotion-28 .e1jf5lit4 { display: none; } } @media (min-width:1024px) { - .emotion-24 .emotion-23 { + .emotion-28 .emotion-27 { padding: 0 20px; } @media (min-width:1275px) { - .emotion-24 .emotion-23 { + .emotion-28 .emotion-27 { max-width: 1240px; width: 100%; margin: 0 auto; @@ -785,7 +850,7 @@ exports[` should display the Loading component at the beginning 1`] = ` } } -.emotion-22 { +.emotion-26 { -webkit-box-pack: justify; -webkit-justify-content: space-between; -ms-flex-pack: justify; @@ -863,7 +928,7 @@ exports[` should display the Loading component at the beginning 1`] = ` overflow-y: auto; } -.emotion-20 { +.emotion-24 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -875,12 +940,32 @@ exports[` should display the Loading component at the beginning 1`] = ` display: block; } +.emotion-20 { + display: none; +} + +@media screen and (min-width:768px) { + .emotion-20 { + display: inline-block; + } +} + .emotion-18 { + display: none; +} + +@media screen and (min-width:768px) { + .emotion-18 { + display: inline-block; + } +} + +.emotion-22 { color: #fff; } @media screen and (min-width:1240px) { - .emotion-26 { + .emotion-30 { max-width: 1240px; width: 100%; margin-left: auto; @@ -888,7 +973,7 @@ exports[` should display the Loading component at the beginning 1`] = ` } } -.emotion-69 { +.emotion-73 { background: #f9f9f9; border-top: 1px solid #e3e3e3; color: #999999; @@ -896,7 +981,7 @@ exports[` should display the Loading component at the beginning 1`] = ` padding: 20px; } -.emotion-67 { +.emotion-71 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -913,7 +998,7 @@ exports[` should display the Loading component at the beginning 1`] = ` } @media (min-width:768px) { - .emotion-67 { + .emotion-71 { min-width: 400px; max-width: 800px; margin: auto; @@ -925,12 +1010,12 @@ exports[` should display the Loading component at the beginning 1`] = ` } @media (min-width:1024px) { - .emotion-67 { + .emotion-71 { max-width: 1240px; } } -.emotion-58 { +.emotion-62 { -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; @@ -939,7 +1024,7 @@ exports[` should display the Loading component at the beginning 1`] = ` } @media (min-width:768px) { - .emotion-58 { + .emotion-62 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -947,21 +1032,21 @@ exports[` should display the Loading component at the beginning 1`] = ` } } -.emotion-28 { +.emotion-32 { color: #e25555; padding: 0 5px; } -.emotion-56 { +.emotion-60 { position: relative; height: 18px; } -.emotion-56:hover .emotion-55 { +.emotion-60:hover .emotion-59 { visibility: visible; } -.emotion-31 { +.emotion-35 { box-sizing: initial; display: inline-block; cursor: default; @@ -970,7 +1055,7 @@ exports[` should display the Loading component at the beginning 1`] = ` padding: 0 10px; } -.emotion-54 { +.emotion-58 { position: absolute; background: #d3dddd; padding: 1px 4px; @@ -988,7 +1073,7 @@ exports[` should display the Loading component at the beginning 1`] = ` top: -2px; } -.emotion-54:before { +.emotion-58:before { content: ''; position: absolute; top: 29%; @@ -1001,7 +1086,7 @@ exports[` should display the Loading component at the beginning 1`] = ` transform: rotate(90deg); } -.emotion-34 { +.emotion-38 { box-sizing: initial; display: inline-block; cursor: default; @@ -1010,7 +1095,7 @@ exports[` should display the Loading component at the beginning 1`] = ` padding: 0 5px; } -.emotion-65 { +.emotion-69 { -webkit-align-items: center; -webkit-box-align: center; -ms-flex-align: center; @@ -1023,7 +1108,7 @@ exports[` should display the Loading component at the beginning 1`] = ` } @media (min-width:768px) { - .emotion-65 { + .emotion-69 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -1031,7 +1116,7 @@ exports[` should display the Loading component at the beginning 1`] = ` } } -.emotion-63 { +.emotion-67 { box-sizing: initial; display: inline-block; cursor: pointer; @@ -1040,21 +1125,21 @@ exports[` should display the Loading component at the beginning 1`] = ` padding: 0 5px; } -.emotion-60 { +.emotion-64 { width: 100%; height: auto; }