feat(ui): initial support for localisation (#8015)

update AppBar to use localisation changes
This commit is contained in:
Chirag Madlani 2022-10-07 17:15:47 +05:30 committed by GitHub
parent 7358c14906
commit 861c846932
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 137 additions and 17 deletions

View File

@ -44,6 +44,8 @@
"fs-extra": "^10.1.0",
"html-react-parser": "^1.2.6",
"https-browserify": "^1.0.0",
"i18next": "^21.10.0",
"i18next-browser-languagedetector": "^6.1.6",
"ieee754": "^1.2.1",
"immutable": "^4.0.0-rc.14",
"jwt-decode": "^3.1.2",
@ -71,6 +73,7 @@
"react-error-boundary": "^3.1.4",
"react-flow-renderer": "^10.3.17",
"react-google-login": "^5.2.2",
"react-i18next": "^11.18.6",
"react-oidc": "^1.0.3",
"react-quill": "^1.3.5",
"react-router-dom": "^5.2.0",

View File

@ -18,6 +18,7 @@ import { isEmpty } from 'lodash';
import { observer } from 'mobx-react';
import { Match } from 'Models';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Link, useHistory, useLocation, useRouteMatch } from 'react-router-dom';
import appState from '../../AppState';
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
@ -52,6 +53,7 @@ const cookieStorage = new CookieStorage();
const Appbar: React.FC = (): JSX.Element => {
const location = useLocation();
const history = useHistory();
const { t } = useTranslation();
const { isFirstTimeUser } = useAuth(location.pathname);
const {
isAuthDisabled,
@ -82,7 +84,7 @@ const Appbar: React.FC = (): JSX.Element => {
{
name: (
<span>
<span className="tw-text-grey-muted">{`Version ${
<span className="tw-text-grey-muted">{`${t('label.version')} ${
(version ? version : '?').split('-')[0]
}`}</span>
</span>
@ -100,7 +102,7 @@ const Appbar: React.FC = (): JSX.Element => {
),
},
{
name: `Docs`,
name: t('label.docs'),
to: urlGitbookDocs,
isOpenNewTab: true,
disabled: false,
@ -114,7 +116,7 @@ const Appbar: React.FC = (): JSX.Element => {
),
},
{
name: `API`,
name: t('label.api-uppercase'),
to: ROUTES.SWAGGER,
disabled: false,
icon: (
@ -127,7 +129,7 @@ const Appbar: React.FC = (): JSX.Element => {
),
},
{
name: `Slack`,
name: t('label.slack'),
to: urlJoinSlack,
disabled: false,
isOpenNewTab: true,
@ -228,7 +230,7 @@ const Appbar: React.FC = (): JSX.Element => {
isText: true,
},
{
name: 'Logout',
name: t('label.logout'),
to: '',
disabled: false,
method: onLogoutHandler,

View File

@ -14,6 +14,7 @@
import { Badge, Dropdown, Image, Input, Space } from 'antd';
import { debounce, toString } from 'lodash';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Link, NavLink, useHistory } from 'react-router-dom';
import AppState from '../../AppState';
import Logo from '../../assets/svg/logo-monogram.svg';
@ -70,6 +71,7 @@ const NavBar = ({
[AppState.userDetails, AppState.nonSecureUserDetails]
);
const history = useHistory();
const { t } = useTranslation();
const [searchIcon, setSearchIcon] = useState<string>('icon-searchv1');
const [suggestionSearch, setSuggestionSearch] = useState<string>('');
const [hasTaskNotification, setHasTaskNotification] =
@ -239,7 +241,7 @@ const NavBar = ({
to={{
pathname: '/explore/tables',
}}>
Explore
{t('label.explore')}
</NavLink>
<NavLink
@ -249,7 +251,7 @@ const NavBar = ({
to={{
pathname: ROUTES.GLOSSARY,
}}>
Glossary
{t('label.glossary')}
</NavLink>
<NavLink
@ -259,7 +261,7 @@ const NavBar = ({
to={{
pathname: ROUTES.TAGS,
}}>
Tags
{t('label.tags')}
</NavLink>
<NavLink
@ -269,7 +271,7 @@ const NavBar = ({
to={{
pathname: ROUTES.SETTINGS,
}}>
Settings
{t('label.settings')}
</NavLink>
</Space>
</div>
@ -281,7 +283,7 @@ const NavBar = ({
className="tw-relative search-grey hover:tw-outline-none focus:tw-outline-none tw-pl-2 tw-pt-2 tw-pb-1.5 tw-ml-4 tw-z-41"
data-testid="searchBox"
id="searchBox"
placeholder="Search for Tables, Topics, Dashboards, Pipelines and ML Models"
placeholder={t('label.search-global')}
style={{
borderRadius: '0.24rem',
boxShadow: 'none',

View File

@ -15,6 +15,10 @@ import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './styles/index.js';
import { initLocale } from './utils/i18next/LocalUtil';
// Initialize locale
initLocale();
ReactDOM.render(
<React.StrictMode>

View File

@ -0,0 +1,17 @@
{
"label": {
"docs": "Docs",
"api-uppercase": "API",
"slack": "Slack",
"logout": "Logout",
"version": "Version",
"explore": "Explore",
"glossary": "Glossary",
"tags": "Tags",
"settings": "Settings",
"search-global": "Search for Tables, Topics, Dashboards, Pipelines and ML Models"
},
"message": {},
"server": {},
"url": {}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright 2021 Collate
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import i18n from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';
import { getInitOptions } from './i18nextUtil';
export const initLocale = (): void => {
// Initialize i18next (language)
i18n
.use(LanguageDetector) // Detects system language
.use(initReactI18next)
.init(getInitOptions());
};

View File

@ -0,0 +1,33 @@
/*
* Copyright 2021 Collate
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { InitOptions } from 'i18next';
import enUS from '../../locale/languages/en-us.json';
// Returns i18next options
export const getInitOptions = (): InitOptions => {
return {
supportedLngs: ['en-US'],
resources: {
'en-US': { translation: enUS },
},
fallbackLng: ['en-US'],
interpolation: {
escapeValue: false, // XSS safety provided by React
},
missingKeyHandler: (_lngs, _ns, key) =>
// eslint-disable-next-line no-console
console.error(`i18next: key not found "${key}"`),
saveMissing: true, // Required for missing key handler
};
};

View File

@ -1871,6 +1871,13 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.14.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.9", "@babel/runtime@^7.19.0":
version "7.19.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.16.3":
version "7.16.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.5.tgz#7f3e34bf8bdbbadf03fbb7b1ea0d929569c9487a"
@ -1878,13 +1885,6 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.18.9":
version "7.19.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/template@^7.14.5", "@babel/template@^7.3.3", "@babel/template@^7.4.0":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4"
@ -7968,6 +7968,13 @@ html-minifier-terser@^5.0.1:
relateurl "^0.2.7"
terser "^4.6.3"
html-parse-stringify@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2"
integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==
dependencies:
void-elements "3.1.0"
html-react-parser@^1.2.6:
version "1.2.8"
resolved "https://registry.yarnpkg.com/html-react-parser/-/html-react-parser-1.2.8.tgz#6806984a5056417de38fc4b52145bd56b1b32d73"
@ -8124,6 +8131,20 @@ husky@^8.0.1:
resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.1.tgz#511cb3e57de3e3190514ae49ed50f6bc3f50b3e9"
integrity sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==
i18next-browser-languagedetector@^6.1.6:
version "6.1.6"
resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.6.tgz#c8a13185bc0d445bd9afcc8be5ab8d343bb259b1"
integrity sha512-5ZErazMh/8ZF5bNmJ9OCvSTzMXzefK9vJMtXekXUkwZ6ZX3XUSagWseQgtbWjo8iiZyCP2lxveKwIBikfVRGDg==
dependencies:
"@babel/runtime" "^7.19.0"
i18next@^21.10.0:
version "21.10.0"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.10.0.tgz#85429af55fdca4858345d0e16b584ec29520197d"
integrity sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==
dependencies:
"@babel/runtime" "^7.17.2"
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"
@ -12459,6 +12480,14 @@ react-google-login@^5.2.2:
"@types/react" "*"
prop-types "^15.6.0"
react-i18next@^11.18.6:
version "11.18.6"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.18.6.tgz#e159c2960c718c1314f1e8fcaa282d1c8b167887"
integrity sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==
dependencies:
"@babel/runtime" "^7.14.5"
html-parse-stringify "^3.0.1"
react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
@ -15012,6 +15041,11 @@ vfile@^5.0.0:
unist-util-stringify-position "^3.0.0"
vfile-message "^3.0.0"
void-elements@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"
integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==
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"