diff --git a/.changeset/cold-humans-check.md b/.changeset/cold-humans-check.md new file mode 100644 index 0000000000..dcc5b649f4 --- /dev/null +++ b/.changeset/cold-humans-check.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-user-settings': patch +--- + +userSetting plugin support i18n diff --git a/plugins/user-settings/report-alpha.api.md b/plugins/user-settings/report-alpha.api.md index 6ba131377a..493b00e801 100644 --- a/plugins/user-settings/report-alpha.api.md +++ b/plugins/user-settings/report-alpha.api.md @@ -106,6 +106,16 @@ export const settingsNavItem: ExtensionDefinition<{ export const userSettingsTranslationRef: TranslationRef< 'user-settings', { + readonly 'featureFlags.title': 'Feature Flags'; + readonly 'featureFlags.description': 'Please refresh the page when toggling feature flags'; + readonly 'featureFlags.emptyFlags.title': 'No Feature Flags'; + readonly 'featureFlags.emptyFlags.action.title': 'An example for how to add a feature flag is highlighted below:'; + readonly 'featureFlags.emptyFlags.action.readMoreButtonTitle': 'Read More'; + readonly 'featureFlags.emptyFlags.description': 'Feature Flags make it possible for plugins to register features in Backstage for users to opt into. You can use this to split out logic in your code for manual A/B testing, etc.'; + readonly 'featureFlags.flagItem.title.disable': 'Disable'; + readonly 'featureFlags.flagItem.title.enable': 'Enable'; + readonly 'featureFlags.flagItem.subTitle.registeredInApplication': 'Registered in the application'; + readonly 'featureFlags.flagItem.subTitle.registeredInPlugin': 'Registered in {{pluginId}} plugin'; readonly 'languageToggle.select': 'Select language {{language}}'; readonly 'languageToggle.title': 'Language'; readonly 'languageToggle.description': 'Change the language'; @@ -116,6 +126,27 @@ export const userSettingsTranslationRef: TranslationRef< readonly 'themeToggle.names.dark': 'Dark'; readonly 'themeToggle.names.light': 'Light'; readonly 'themeToggle.selectAuto': 'Select Auto Theme'; + readonly 'signOutMenu.title': 'Sign Out'; + readonly 'pinToggle.title': 'Pin Sidebar'; + readonly 'pinToggle.description': 'Prevent the sidebar from collapsing'; + readonly 'identityCard.title': 'Backstage Identity'; + readonly 'identityCard.noIdentityTitle': 'No Backstage Identity'; + readonly 'identityCard.userEntity': 'User Entity'; + readonly 'identityCard.ownershipEntities': 'Ownership Entities'; + readonly 'defaultProviderSettings.description': 'Provides authentication towards {{provider}} APIs and identities'; + readonly 'emptyProviders.title': 'No Authentication Providers'; + readonly 'emptyProviders.action.title': 'Open app-config.yaml and make the changes as highlighted below:'; + readonly 'emptyProviders.action.readMoreButtonTitle': 'Read More'; + readonly 'emptyProviders.description': 'You can add Authentication Providers to Backstage which allows you to use these providers to authenticate yourself.'; + readonly 'providerSettingsItem.title.signIn': 'Sign in to {{title}}'; + readonly 'providerSettingsItem.title.signOut': 'Sign out from {{title}}'; + readonly 'providerSettingsItem.buttonTitle.signIn': 'Sign in'; + readonly 'providerSettingsItem.buttonTitle.signOut': 'Sign out'; + readonly 'authProviders.title': 'Available Providers'; + readonly 'defaultSettingsPage.tabsTitle.featureFlags': 'Feature Flags'; + readonly 'defaultSettingsPage.tabsTitle.authProviders': 'Authentication Providers'; + readonly 'defaultSettingsPage.tabsTitle.general': 'General'; + readonly 'settingsLayout.title': 'Settings'; } >; diff --git a/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx b/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx index 71afb789b7..b0ddbf31cf 100644 --- a/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx +++ b/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx @@ -27,18 +27,23 @@ import { atlassianAuthApiRef, oneloginAuthApiRef, } from '@backstage/core-plugin-api'; +import { userSettingsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; /** @public */ export const DefaultProviderSettings = (props: { configuredProviders: string[]; }) => { const { configuredProviders } = props; + const { t } = useTranslationRef(userSettingsTranslationRef); return ( <> {configuredProviders.includes('google') && ( @@ -46,7 +51,9 @@ export const DefaultProviderSettings = (props: { {configuredProviders.includes('microsoft') && ( @@ -54,7 +61,9 @@ export const DefaultProviderSettings = (props: { {configuredProviders.includes('github') && ( @@ -62,7 +71,9 @@ export const DefaultProviderSettings = (props: { {configuredProviders.includes('gitlab') && ( @@ -70,7 +81,9 @@ export const DefaultProviderSettings = (props: { {configuredProviders.includes('okta') && ( @@ -78,7 +91,9 @@ export const DefaultProviderSettings = (props: { {configuredProviders.includes('bitbucket') && ( @@ -86,7 +101,9 @@ export const DefaultProviderSettings = (props: { {configuredProviders.includes('onelogin') && ( @@ -94,7 +111,9 @@ export const DefaultProviderSettings = (props: { {configuredProviders.includes('atlassian') && ( @@ -102,7 +121,9 @@ export const DefaultProviderSettings = (props: { {configuredProviders.includes('bitbucketServer') && ( diff --git a/plugins/user-settings/src/components/AuthProviders/EmptyProviders.tsx b/plugins/user-settings/src/components/AuthProviders/EmptyProviders.tsx index 05c4e52735..ecf1993845 100644 --- a/plugins/user-settings/src/components/AuthProviders/EmptyProviders.tsx +++ b/plugins/user-settings/src/components/AuthProviders/EmptyProviders.tsx @@ -17,6 +17,8 @@ import Button from '@material-ui/core/Button'; import Typography from '@material-ui/core/Typography'; import { CodeSnippet, EmptyState } from '@backstage/core-components'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { userSettingsTranslationRef } from '../../translation'; const EXAMPLE = `auth: providers: @@ -26,32 +28,34 @@ const EXAMPLE = `auth: clientSecret: \${AUTH_GOOGLE_CLIENT_SECRET} `; -export const EmptyProviders = () => ( - - - Open app-config.yaml and make the changes as highlighted - below: - - - - - } - /> -); +export const EmptyProviders = () => { + const { t } = useTranslationRef(userSettingsTranslationRef); + return ( + + + {t('emptyProviders.action.title')} + + + + + } + /> + ); +}; diff --git a/plugins/user-settings/src/components/AuthProviders/ProviderSettingsItem.tsx b/plugins/user-settings/src/components/AuthProviders/ProviderSettingsItem.tsx index b64264271a..32eaeb0cb9 100644 --- a/plugins/user-settings/src/components/AuthProviders/ProviderSettingsItem.tsx +++ b/plugins/user-settings/src/components/AuthProviders/ProviderSettingsItem.tsx @@ -34,6 +34,8 @@ import { IconComponent, } from '@backstage/core-plugin-api'; import { ProviderSettingsAvatar } from './ProviderSettingsAvatar'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { userSettingsTranslationRef } from '../../translation'; const emptyProfile: ProfileInfo = {}; @@ -50,6 +52,7 @@ export const ProviderSettingsItem = (props: { const errorApi = useApi(errorApiRef); const [signedIn, setSignedIn] = useState(false); const [profile, setProfile] = useState(emptyProfile); + const { t } = useTranslationRef(userSettingsTranslationRef); useEffect(() => { let didCancel = false; @@ -128,7 +131,11 @@ export const ProviderSettingsItem = (props: { diff --git a/plugins/user-settings/src/components/AuthProviders/UserSettingsAuthProviders.tsx b/plugins/user-settings/src/components/AuthProviders/UserSettingsAuthProviders.tsx index f22cd5e2f6..bd511146e0 100644 --- a/plugins/user-settings/src/components/AuthProviders/UserSettingsAuthProviders.tsx +++ b/plugins/user-settings/src/components/AuthProviders/UserSettingsAuthProviders.tsx @@ -19,6 +19,8 @@ import { EmptyProviders } from './EmptyProviders'; import { DefaultProviderSettings } from './DefaultProviderSettings'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { InfoCard } from '@backstage/core-components'; +import { userSettingsTranslationRef } from '../../translation'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; /** @public */ export const UserSettingsAuthProviders = (props: { @@ -31,13 +33,14 @@ export const UserSettingsAuthProviders = (props: { const providers = providerSettings ?? ( ); + const { t } = useTranslationRef(userSettingsTranslationRef); if (!providerSettings && !configuredProviders?.length) { return ; } return ( - + {providers} ); diff --git a/plugins/user-settings/src/components/DefaultSettingsPage/DefaultSettingsPage.tsx b/plugins/user-settings/src/components/DefaultSettingsPage/DefaultSettingsPage.tsx index 49504b67d6..87a2dd212b 100644 --- a/plugins/user-settings/src/components/DefaultSettingsPage/DefaultSettingsPage.tsx +++ b/plugins/user-settings/src/components/DefaultSettingsPage/DefaultSettingsPage.tsx @@ -19,6 +19,8 @@ import { UserSettingsAuthProviders } from '../AuthProviders'; import { UserSettingsFeatureFlags } from '../FeatureFlags'; import { UserSettingsGeneral } from '../General'; import { SettingsLayout, SettingsLayoutRouteProps } from '../SettingsLayout'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { userSettingsTranslationRef } from '../../translation'; /** * @public @@ -28,19 +30,26 @@ export const DefaultSettingsPage = (props: { providerSettings?: JSX.Element; }) => { const { providerSettings, tabs } = props; + const { t } = useTranslationRef(userSettingsTranslationRef); return ( - + - + {tabs} diff --git a/plugins/user-settings/src/components/FeatureFlags/EmptyFlags.tsx b/plugins/user-settings/src/components/FeatureFlags/EmptyFlags.tsx index 8ba1e9192f..54847f40a5 100644 --- a/plugins/user-settings/src/components/FeatureFlags/EmptyFlags.tsx +++ b/plugins/user-settings/src/components/FeatureFlags/EmptyFlags.tsx @@ -17,6 +17,8 @@ import Button from '@material-ui/core/Button'; import Typography from '@material-ui/core/Typography'; import { CodeSnippet, EmptyState } from '@backstage/core-components'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { userSettingsTranslationRef } from '../../translation'; const EXAMPLE = `import { createPlugin } from '@backstage/core-plugin-api'; @@ -26,31 +28,35 @@ export default createPlugin({ }); `; -export const EmptyFlags = () => ( - - - An example for how to add a feature flag is highlighted below: - - - - - } - /> -); +export const EmptyFlags = () => { + const { t } = useTranslationRef(userSettingsTranslationRef); + + return ( + + + {t('featureFlags.emptyFlags.action.title')} + + + + + } + /> + ); +}; diff --git a/plugins/user-settings/src/components/FeatureFlags/FeatureFlagsItem.tsx b/plugins/user-settings/src/components/FeatureFlags/FeatureFlagsItem.tsx index fa31534257..49e8e57fc4 100644 --- a/plugins/user-settings/src/components/FeatureFlags/FeatureFlagsItem.tsx +++ b/plugins/user-settings/src/components/FeatureFlags/FeatureFlagsItem.tsx @@ -20,6 +20,9 @@ import ListItemIcon from '@material-ui/core/ListItemIcon'; import Switch from '@material-ui/core/Switch'; import Tooltip from '@material-ui/core/Tooltip'; import { FeatureFlag } from '@backstage/core-plugin-api'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { userSettingsTranslationRef } from '../../translation'; +import { TranslationFunction } from '@backstage/core-plugin-api/alpha'; type Props = { flag: FeatureFlag; @@ -27,22 +30,39 @@ type Props = { toggleHandler: Function; }; -const getSecondaryText = (flag: FeatureFlag) => { +const getSecondaryText = ( + flag: FeatureFlag, + t: TranslationFunction, +) => { if (flag.description) { return flag.description; } return flag.pluginId - ? `Registered in ${flag.pluginId} plugin` - : 'Registered in the application'; + ? t('featureFlags.flagItem.subTitle.registeredInPlugin', { + pluginId: flag.pluginId, + }) + : t('featureFlags.flagItem.subTitle.registeredInApplication'); }; -export const FlagItem = ({ flag, enabled, toggleHandler }: Props) => ( - toggleHandler(flag.name)}> - - - - - - - -); +export const FlagItem = ({ flag, enabled, toggleHandler }: Props) => { + const { t } = useTranslationRef(userSettingsTranslationRef); + + return ( + toggleHandler(flag.name)}> + + + + + + + + ); +}; diff --git a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx index d498d8ab0a..49975542c4 100644 --- a/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx +++ b/plugins/user-settings/src/components/FeatureFlags/UserSettingsFeatureFlags.tsx @@ -31,6 +31,8 @@ import { } from '@backstage/core-plugin-api'; import { InfoCard } from '@backstage/core-components'; import ClearIcon from '@material-ui/icons/Clear'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { userSettingsTranslationRef } from '../../translation'; export const sortFlags = ( flags: FeatureFlag[], @@ -59,6 +61,7 @@ export const UserSettingsFeatureFlags = () => { const [state, setState] = useState>(initialFlagState); const [filterInput, setFilterInput] = useState(''); + const { t } = useTranslationRef(userSettingsTranslationRef); const toggleFlag = useCallback( (flagName: string) => { @@ -96,9 +99,9 @@ export const UserSettingsFeatureFlags = () => { const Header = () => ( - Feature Flags + {t('featureFlags.title')} - Please refresh the page when toggling feature flags + {t('featureFlags.description')} {featureFlags.length >= 10 && ( diff --git a/plugins/user-settings/src/components/General/UserSettingsIdentityCard.tsx b/plugins/user-settings/src/components/General/UserSettingsIdentityCard.tsx index 95e2469013..1f538c65ac 100644 --- a/plugins/user-settings/src/components/General/UserSettingsIdentityCard.tsx +++ b/plugins/user-settings/src/components/General/UserSettingsIdentityCard.tsx @@ -19,25 +19,28 @@ import { EntityRefLinks } from '@backstage/plugin-catalog-react'; import Grid from '@material-ui/core/Grid'; import Typography from '@material-ui/core/Typography'; import { useUserProfile } from '../useUserProfileInfo'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { userSettingsTranslationRef } from '../../translation'; const Contents = () => { const { backstageIdentity } = useUserProfile(); + const { t } = useTranslationRef(userSettingsTranslationRef); if (!backstageIdentity) { - return No Backstage Identity; + return {t('identityCard.noIdentityTitle')}; } return ( - User Entity:{' '} + {t('identityCard.userEntity')}:{' '} - Ownership Entities:{' '} + {t('identityCard.ownershipEntities')}:{' '} @@ -46,8 +49,12 @@ const Contents = () => { }; /** @public */ -export const UserSettingsIdentityCard = () => ( - - - -); +export const UserSettingsIdentityCard = () => { + const { t } = useTranslationRef(userSettingsTranslationRef); + + return ( + + + + ); +}; diff --git a/plugins/user-settings/src/components/General/UserSettingsMenu.tsx b/plugins/user-settings/src/components/General/UserSettingsMenu.tsx index 28c0737a86..0ba56da318 100644 --- a/plugins/user-settings/src/components/General/UserSettingsMenu.tsx +++ b/plugins/user-settings/src/components/General/UserSettingsMenu.tsx @@ -26,6 +26,8 @@ import { errorApiRef, useApi, } from '@backstage/core-plugin-api'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { userSettingsTranslationRef } from '../../translation'; /** @public */ export const UserSettingsMenu = () => { @@ -33,6 +35,7 @@ export const UserSettingsMenu = () => { const identityApi = useApi(identityApiRef); const [open, setOpen] = useState(false); const [anchorEl, setAnchorEl] = useState(undefined); + const { t } = useTranslationRef(userSettingsTranslationRef); const handleOpen = (event: MouseEvent) => { setAnchorEl(event.currentTarget); @@ -63,7 +66,7 @@ export const UserSettingsMenu = () => { - Sign Out + {t('signOutMenu.title')} diff --git a/plugins/user-settings/src/components/General/UserSettingsPinToggle.tsx b/plugins/user-settings/src/components/General/UserSettingsPinToggle.tsx index 5947c31e9a..8852db758e 100644 --- a/plugins/user-settings/src/components/General/UserSettingsPinToggle.tsx +++ b/plugins/user-settings/src/components/General/UserSettingsPinToggle.tsx @@ -20,16 +20,19 @@ import ListItemText from '@material-ui/core/ListItemText'; import Switch from '@material-ui/core/Switch'; import Tooltip from '@material-ui/core/Tooltip'; import { useSidebarPinState } from '@backstage/core-components'; +import { useTranslationRef } from '@backstage/frontend-plugin-api'; +import { userSettingsTranslationRef } from '../../translation'; /** @public */ export const UserSettingsPinToggle = () => { const { isPinned, toggleSidebarPinState } = useSidebarPinState(); + const { t } = useTranslationRef(userSettingsTranslationRef); return ( { const { title, children } = props; const { isMobile } = useSidebarPinState(); + const { t } = useTranslationRef(userSettingsTranslationRef); const routes = useElementFilter(children, elements => elements @@ -71,7 +74,7 @@ export const SettingsLayout = (props: SettingsLayoutProps) => { return ( - {!isMobile &&
} + {!isMobile &&
} ); diff --git a/plugins/user-settings/src/translation.ts b/plugins/user-settings/src/translation.ts index 411ca1af51..0f1ba92bbd 100644 --- a/plugins/user-settings/src/translation.ts +++ b/plugins/user-settings/src/translation.ts @@ -36,5 +36,80 @@ export const userSettingsTranslationRef = createTranslationRef({ auto: 'Auto', }, }, + signOutMenu: { + title: 'Sign Out', + }, + pinToggle: { + title: 'Pin Sidebar', + description: 'Prevent the sidebar from collapsing', + }, + identityCard: { + title: 'Backstage Identity', + noIdentityTitle: 'No Backstage Identity', + userEntity: 'User Entity', + ownershipEntities: 'Ownership Entities', + }, + defaultProviderSettings: { + description: + 'Provides authentication towards {{provider}} APIs and identities', + }, + emptyProviders: { + title: 'No Authentication Providers', + description: + 'You can add Authentication Providers to Backstage which allows you to use these providers to authenticate yourself.', + action: { + title: + 'Open app-config.yaml and make the changes as highlighted below:', + readMoreButtonTitle: 'Read More', + }, + }, + providerSettingsItem: { + title: { + signIn: 'Sign in to {{title}}', + signOut: 'Sign out from {{title}}', + }, + buttonTitle: { + signIn: 'Sign in', + signOut: 'Sign out', + }, + }, + authProviders: { + title: 'Available Providers', + }, + defaultSettingsPage: { + tabsTitle: { + general: 'General', + authProviders: 'Authentication Providers', + featureFlags: 'Feature Flags', + }, + }, + featureFlags: { + title: 'Feature Flags', + description: 'Please refresh the page when toggling feature flags', + emptyFlags: { + title: 'No Feature Flags', + description: + 'Feature Flags make it possible for plugins to register features in Backstage for users to opt into. You can use this to split out logic in your code for manual A/B testing, etc.', + action: { + title: + 'An example for how to add a feature flag is highlighted below:', + readMoreButtonTitle: 'Read More', + }, + }, + flagItem: { + title: { + disable: 'Disable', + enable: 'Enable', + }, + subTitle: { + registeredInApplication: 'Registered in the application', + registeredInPlugin: 'Registered in {{pluginId}} plugin', + }, + }, + }, + general: {}, + settingsLayout: { + title: 'Settings', + }, }, });