Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dynamic-demo-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ namespace. For example:
```

Note that you will need to include a comment in a TypeScript file like the
following for [i18next-parser](https://github.com/i18next/i18next-parser) to
following for [i18next-cli](https://github.com/i18next/i18next-cli) to
add the message from `console-extensions.json` to your message catalog.

```ts
Expand Down
12 changes: 0 additions & 12 deletions dynamic-demo-plugin/i18next-parser.config.js

This file was deleted.

58 changes: 58 additions & 0 deletions dynamic-demo-plugin/i18next.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { readFile } from 'node:fs/promises';
import jsonc from 'comment-json';
import { defineConfig, Plugin } from 'i18next-cli';

/**
* Custom JSON parser for localizing keys matching format: /%.+%/
*/
const consoleExtensionsPlugin = (): Plugin => ({
name: 'console-extensions',

async onEnd(keys) {
const content = await readFile('console-extensions.json', 'utf-8');
const extracted: { key: string }[] = [];

try {
jsonc.parse(
content,
(_key, value) => {
if (typeof value === 'string') {
const match = value.match(/^%(.+)%$/);
if (match && match[1]) {
extracted.push({ key: match[1] });
}
}
return value;
},
true,
);
} catch (e) {
console.error('Failed to parse as JSON.', e);
extracted.length = 0;
}

for (const { key: fullKey } of extracted) {
const [ns, key] = fullKey.split('~', 2);
Comment thread
logonoff marked this conversation as resolved.

if (ns && key) {
keys.set(`${ns}:${key}`, { key, defaultValue: key, ns });
} else {
console.warn(`Invalid key format: ${fullKey}`);
}
}
},
});

export default defineConfig({
locales: ['en'],
extract: {
input: 'src/**/*.{js,jsx,ts,tsx}',
output: 'locales/{{language}}/{{namespace}}.json',

sort: true,
keySeparator: false,
nsSeparator: '~',
defaultNS: 'plugin__console-demo-plugin',
},
plugins: [consoleExtensionsPlugin()],
});
140 changes: 73 additions & 67 deletions dynamic-demo-plugin/locales/en/plugin__console-demo-plugin.json
Original file line number Diff line number Diff line change
@@ -1,93 +1,99 @@
{
"{{count}} Worker Node": "{{count}} Worker Node",
"{{count}} Worker Node_plural": "{{count}} Worker Nodes",
"Worker Nodes": "Worker Nodes",
"Custom Overview Detail Info": "Custom Overview Detail Info",
"Metrics Dashboard Card example": "Metrics Dashboard Card example",
"Oops something went wrong in your dynamic plug-in": "Oops something went wrong in your dynamic plug-in",
"Sample Error Boundary Page": "Sample Error Boundary Page",
"{{count}} Cron Job_one": "{{count}} Cron Job",
"{{count}} Cron Job_other": "{{count}} Cron Jobs",
"{{count}} Worker Node_one": "{{count}} Worker Node",
"{{count}} Worker Node_other": "{{count}} Worker Nodes",
"A great way to start your day is with some toast and a cup of coffee.": "A great way to start your day is with some toast and a cup of coffee.",
"An error occurred.": "An error occurred.",
"An error occurred. Please try again.": "An error occurred. Please try again.",
"API Server Events": "API Server Events",
"Bar item": "Bar item",
"Cancel": "Cancel",
"Card content goes here.": "Card content goes here.",
"Close": "Close",
"Component is resolving": "Component is resolving",
"Create": "Create",
"Create an exception": "Create an exception",
"Launch buggy component": "Launch buggy component",
"Example Namespaced Page": "Example Namespaced Page",
"Example page with a namespace bar": "Example page with a namespace bar",
"Create Pod": "Create Pod",
"Create Project": "Create Project",
"Cron Jobs": "Cron Jobs",
"Currently selected namespace": "Currently selected namespace",
"Custom Overview Detail Info": "Custom Overview Detail Info",
"Custom Overview Detail Title": "Custom Overview Detail Title",
"Demo": "Demo",
"Demo Dashboard": "Demo Dashboard",
"Demo Plugin": "Demo Plugin",
"Demo prometheus activity": "Demo prometheus activity",
"Description": "Description",
"Dismiss Toasts": "Dismiss Toasts",
"Display name": "Display name",
"Dynamic Nav 1": "Dynamic Nav 1",
"Dynamic Nav 2": "Dynamic Nav 2",
"Dynamic Page 1": "Dynamic Page 1",
"Dynamic Page 2": "Dynamic Page 2",
"Dynamic Plugin Proxy Services example": "Dynamic Plugin Proxy Services example",
"Example card": "Example card",
"Example hint": "Example hint",
"Example info alert": "Example info alert",
"Example Namespaced Page": "Example Namespaced Page",
"Example page with a namespace bar": "Example page with a namespace bar",
"Example Resource Details Page": "Example Resource Details Page",
"Example Resource List Page": "Example Resource List Page",
"Example warning alert": "Example warning alert",
"Example hint": "Example hint",
"This page shows an example gallery view with cards": "This page shows an example gallery view with cards",
"Example card": "Example card",
"Card content goes here.": "Card content goes here.",
"Prometheus error": "Prometheus error",
"Prometheus loading": "Prometheus loading",
"Prometheus data": "Prometheus data",
"Dynamic Plugin Proxy Services example": "Dynamic Plugin Proxy Services example",
"Proxy: consoleFetchJSON": "Proxy: consoleFetchJSON",
"Test Consumer": "Test Consumer",
"Extensions of type Console.flag/Model": "Extensions of type Console.flag/Model",
"Foo item": "Foo item",
"Group": "Group",
"Version": "Version",
"Kind": "Kind",
"Hello {{planet}}! I am Loki!": "Hello {{planet}}! I am Loki!",
"Hello {{planet}}! I am Thor!": "Hello {{planet}}! I am Thor!",
"Horizontal Nav": "Horizontal Nav",
"K8s API": "K8s API",
"K8s API from Dynamic Plugin SDK": "K8s API from Dynamic Plugin SDK",
"k8sCreate": "k8sCreate",
"k8sDelete": "k8sDelete",
"k8sGet": "k8sGet",
"k8sList": "k8sList",
"k8sPatch": "k8sPatch",
"k8sUpdate": "k8sUpdate",
"k8sList": "k8sList",
"k8sDelete": "k8sDelete",
"Kind": "Kind",
"Launch buggy component": "Launch buggy component",
"Launch Modal": "Launch Modal",
"Launch Modal Asynchronously": "Launch Modal Asynchronously",
"Launch Modal with ID 1": "Launch Modal with ID 1",
"Launch Modal with ID 2": "Launch Modal with ID 2",
"Launch overlay": "Launch overlay",
"Launch overlay modal": "Launch overlay modal",
"Launch overlay with props": "Launch overlay with props",
"List Page": "List Page",
"Metrics Dashboard Card example": "Metrics Dashboard Card example",
"Modal Launchers": "Modal Launchers",
"Name": "Name",
"Namespace": "Namespace",
"List Page": "List Page",
"Oops something went wrong in your dynamic plugin": "Oops something went wrong in your dynamic plugin",
"OpenShift Pods List Page": "OpenShift Pods List Page",
"Create Pod": "Create Pod",
"Sample ResourceIcon": "Sample ResourceIcon",
"An error occurred. Please try again.": "An error occurred. Please try again.",
"Create Project": "Create Project",
"This modal is created with an extension.": "This modal is created with an extension.",
"Display name": "Display name",
"Description": "Description",
"An error occurred.": "An error occurred.",
"Create": "Create",
"Cancel": "Cancel",
"Overlay modal": "Overlay modal",
"ProjectRequest": "ProjectRequest",
"ProjectRequests": "ProjectRequests",
"Prometheus data": "Prometheus data",
"Prometheus error": "Prometheus error",
"Prometheus loading": "Prometheus loading",
"Proxy: consoleFetchJSON": "Proxy: consoleFetchJSON",
"Sample Error Boundary Page": "Sample Error Boundary Page",
"Sample ResourceIcon": "Sample ResourceIcon",
"Show Toast": "Show Toast",
"Storage Classes": "Storage Classes",
"StorageClasses present in this cluster:": "StorageClasses present in this cluster:",
"Component is resolving": "Component is resolving",
"Test overlay with props": "Test overlay with props",
"Test Consumer": "Test Consumer",
"Test modal launched with useOverlay": "Test modal launched with useOverlay",
"Overlay modal": "Overlay modal",
"Modal Launchers": "Modal Launchers",
"Launch Modal": "Launch Modal",
"Launch Modal Asynchronously": "Launch Modal Asynchronously",
"Launch Modal with ID 1": "Launch Modal with ID 1",
"Launch Modal with ID 2": "Launch Modal with ID 2",
"Launch overlay": "Launch overlay",
"Launch overlay with props": "Launch overlay with props",
"Launch overlay modal": "Launch overlay modal",
"Hello {{planet}}! I am Thor!": "Hello {{planet}}! I am Thor!",
"Hello {{planet}}! I am Loki!": "Hello {{planet}}! I am Loki!",
"{{count}} Cron Job": "{{count}} Cron Job",
"{{count}} Cron Job_plural": "{{count}} Cron Jobs",
"Cron Jobs": "Cron Jobs",
"Toast Title": "Toast Title",
"A great way to start your day is with some toast and a cup of coffee.": "A great way to start your day is with some toast and a cup of coffee.",
"Test Modal with ID {{id}}": "Test Modal with ID {{id}}",
"Test Modal with ID {{id}} and testProp {{testProp}}": "Test Modal with ID {{id}} and testProp {{testProp}}",
"Test overlay with props": "Test overlay with props",
"Test Utilities": "Test Utilities",
"This modal is created with an extension.": "This modal is created with an extension.",
"This page shows an example gallery view with cards": "This page shows an example gallery view with cards",
"Toast Title": "Toast Title",
"Utilities from Dynamic Plugin SDK": "Utilities from Dynamic Plugin SDK",
"Utility: consoleFetchJSON": "Utility: consoleFetchJSON",
"Utility: useToast": "Utility: useToast",
"Show Toast": "Show Toast",
"Dismiss Toasts": "Dismiss Toasts",
"Demo": "Demo",
"Demo Plugin": "Demo Plugin",
"Dynamic Nav 1": "Dynamic Nav 1",
"Dynamic Nav 2": "Dynamic Nav 2",
"Foo item": "Foo item",
"Bar item": "Bar item",
"Demo Dashboard": "Demo Dashboard",
"Custom Overview Detail Title": "Custom Overview Detail Title",
"Dashboard Card": "Dashboard Card",
"Horizontal Nav": "Horizontal Nav",
"Dynamic Page 1": "Dynamic Page 1",
"Dynamic Page 2": "Dynamic Page 2"
"Version": "Version",
"Worker Nodes": "Worker Nodes"
}

This file was deleted.

4 changes: 2 additions & 2 deletions dynamic-demo-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"install-plugin-sdk": "rm -rf node_modules/@openshift-console && yarn install",
"start-console": "./start-console.sh",
"http-server": "./http-server.sh dist",
"i18n": "i18next \"src/**/*.{js,jsx,ts,tsx}\" -c i18next-parser.config.js",
"i18n": "i18next-cli lint && i18next-cli extract",
"ts-node": "NODE_OPTIONS='--preserve-symlinks' ts-node -O '{\"module\":\"commonjs\"}'"
},
"devDependencies": {
Expand All @@ -30,7 +30,7 @@
"file-loader": "6.2.0",
"http-server": "^14.1.1",
"i18next": "^25.8.18",
"i18next-parser": "^3.3.0",
"i18next-cli": "1.50.3",
"js-yaml": "^4.1.1",
"react": "18.3.1",
"react-dom": "18.3.1",
Expand Down
4 changes: 3 additions & 1 deletion dynamic-demo-plugin/src/components/APIServerEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from '@openshift-console/dynamic-plugin-sdk';
import { PageSection, Title } from '@patternfly/react-core';
import * as React from 'react';
import { useTranslation } from 'react-i18next';

const apiServerResource: WatchK8sResource = {
kind: 'Deployment',
Expand All @@ -16,11 +17,12 @@ const apiServerResource: WatchK8sResource = {

const APIServerEvents: React.FC = () => {
const [object, loaded, loadError] = useK8sWatchResource<K8sResourceCommon>(apiServerResource);
const { t } = useTranslation('plugin__console-demo-plugin');

return (
<>
<PageSection>
<Title headingLevel="h1">API Server Events</Title>
<Title headingLevel="h1">{t('API Server Events')}</Title>
</PageSection>
<PageSection>
{loaded && !loadError && <ResourceEventStream resource={object} />}
Expand Down
16 changes: 10 additions & 6 deletions dynamic-demo-plugin/src/components/ClusterOverview/Activity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '@openshift-console/dynamic-plugin-sdk';
import { Progress, ProgressSize } from '@patternfly/react-core';
import { InProgressIcon } from '@patternfly/react-icons';
import { useTranslation } from 'react-i18next';

export const DemoActivity: React.FC<K8sActivityProps> = ({ resource }) => (
<>
Expand All @@ -20,12 +21,15 @@ export const DemoActivity: React.FC<K8sActivityProps> = ({ resource }) => (
</>
);

export const DemoPrometheusActivity: React.FC<PrometheusActivityProps> = () => (
<div>
<InProgressIcon />
Demo prometheus activity
</div>
);
export const DemoPrometheusActivity: React.FC<PrometheusActivityProps> = () => {
const { t } = useTranslation('plugin__console-demo-plugin');
return (
<div>
<InProgressIcon />
{t('Demo prometheus activity')}
</div>
);
};

export const isActivity = (resource: K8sResourceCommon) =>
get(resource, ['metadata', 'labels', 'node-role.kubernetes.io/master']) === '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class DemoErrorBoundaryWithTranslation extends React.Component<DemoErrorBoundary
const { error, errorInfo } = this.state;
const FallbackComponent = this.props.FallbackComponent || DefaultFallback;
if (error) {
return <FallbackComponent title={t('plugin__console-demo-plugin~Oops something went wrong in your dynamic plug-in')} errorMessage={error?.message} componentStack={errorInfo?.componentStack} stack={error?.stack} />;
return <FallbackComponent title={t('Oops something went wrong in your dynamic plugin')} errorMessage={error?.message} componentStack={errorInfo?.componentStack} stack={error?.stack} />;
}
return this.props.children;
}
Expand Down
Loading