Skip to content
Draft
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 .ci-operator.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
build_root_image:
name: nodejs-18
namespace: openshift
tag: latest
tag: latest
22 changes: 11 additions & 11 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,31 @@ reviews:
enabled: true
drafts: false
path_instructions:
- path: "src/views/*/manifest.ts"
- path: 'src/views/*/manifest.ts'
instructions: |
These are console extension declarations. Verify that:
- Extension types match the intended console integration point
- $codeRef paths match actual file exports
- Feature flags are applied where needed (NET_ATTACH_DEF, KUBEVIRT_DYNAMIC, FLAG_UDN_ENABLED)
- path: "src/utils/models/**"
- path: 'src/utils/models/**'
instructions: |
K8s model definitions. Verify apiGroup, apiVersion, kind, and plural match the actual CRD.
- path: "src/views/*/form/**"
- path: 'src/views/*/form/**'
instructions: |
Form components use react-hook-form. Check for proper validation, error handling, and i18n usage.
- path: "locales/**"
- path: 'locales/**'
instructions: |
Translation files. These are auto-generated by `npm run i18n` and should not be manually edited
except for non-English locales which are managed by the translation team.
- path: "src/utils/telemetry/**"
- path: 'src/utils/telemetry/**'
instructions: |
Telemetry events. Verify event names and properties follow existing conventions in constants.ts.
path_filters:
- "!dist/**"
- "!node_modules/**"
- "!package-lock.json"
- "!locales/en/**"
- "!**/*.snap"
- "!charts/**/*.yaml"
- '!dist/**'
- '!node_modules/**'
- '!package-lock.json'
- '!locales/en/**'
- '!**/*.snap'
- '!charts/**/*.yaml'
chat:
auto_reply: true
2 changes: 1 addition & 1 deletion .cursor/rules/networking-console-plugin.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ OpenShift Console dynamic plugin for networking UI. React 18 + TypeScript 5.9 +
- **Routing: `react-router` v7 (not `react-router-dom`)
- No `console.*` — use `networkConsole` from `@utils/utils/helpers`
- No hex colors — PatternFly CSS variables only
- **Linting:** ESLint + Prettier, single quotes, trailing commas, 100-char width, `simple-import-sort`
- **Linting:** ESLint and Prettier as separate steps, single quotes, trailing commas, 100-char width, `simple-import-sort`
- **Views follow**: `actions/`, `details/`, `form/`, `list/`, `manifest.ts`
- **Feature flags**: `NET_ATTACH_DEF`, `KUBEVIRT_DYNAMIC`, `FLAG_UDN_ENABLED`
- **SDK hooks for K8s ops**: `useK8sWatchResource`, `k8sCreate`, `k8sPatch`, `k8sDelete`
Expand Down
24 changes: 12 additions & 12 deletions .cursor/skills/i18n-memsource/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ Read and update `.cursor/skills/i18n-memsource/state.json` after each upload.

## Plugin config

| Field | Value |
|-------|-------|
| Namespace / locale file | `plugin__networking-console-plugin` |
| Memsource template ID | `zBOwr4BxYwEq7xlJ37c1F3` |
| Project title | `[OCP $VERSION] UI Localization networking-console-plugin - Sprint $SPRINT/Branch $BRANCH` |
| Languages | `ja`, `zh-cn`, `ko`, `fr`, `es` |
| Locale dirs on disk | `en`, `es`, `fr`, `ja`, `ko`, **`zh`** (not `zh-cn`) |
| PO filename pattern | `po-files/<lang>/plugin__networking-console-plugin.po` (no `public__` prefix) |
| Field | Value |
| ----------------------- | ------------------------------------------------------------------------------------------ |
| Namespace / locale file | `plugin__networking-console-plugin` |
| Memsource template ID | `zBOwr4BxYwEq7xlJ37c1F3` |
| Project title | `[OCP $VERSION] UI Localization networking-console-plugin - Sprint $SPRINT/Branch $BRANCH` |
| Languages | `ja`, `zh-cn`, `ko`, `fr`, `es` |
| Locale dirs on disk | `en`, `es`, `fr`, `ja`, `ko`, **`zh`** (not `zh-cn`) |
| PO filename pattern | `po-files/<lang>/plugin__networking-console-plugin.po` (no `public__` prefix) |

## Prerequisites

Expand Down Expand Up @@ -127,10 +127,10 @@ may treat as already translated.

**Desired PO state before upload:**

| Locale JSON value | msgstr in PO |
|-------------------|--------------|
| Real non-English translation | Keep it (carry forward) |
| Empty `""` | Empty (needs translation) |
| Locale JSON value | msgstr in PO |
| --------------------------------------- | ----------------------------- |
| Real non-English translation | Keep it (carry forward) |
| Empty `""` | Empty (needs translation) |
| English placeholder (== English source) | **Empty** (needs translation) |

`export-pos.sh` runs `i18n-scripts/clear-english-msgstr.js` after generating POs
Expand Down
46 changes: 23 additions & 23 deletions .cursor/skills/i18n-memsource/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ which can drop most custom scripts including PO conversion and

In Cursor, attach or invoke the **i18n-memsource** skill, then ask for one of:

| You say… | Skill runs… |
|----------|-------------|
| "upload translations" / "memsource upload" | Extract keys → build POs (keeping existing translations) → upload to Phrase |
| "download translations" / "memsource download" | Pull finished translations → convert to locale JSON → commit → optional PR |
| "translation status" / "memsource status" | Show Phrase job status per language |
| You say… | Skill runs… |
| ---------------------------------------------- | --------------------------------------------------------------------------- |
| "upload translations" / "memsource upload" | Extract keys → build POs (keeping existing translations) → upload to Phrase |
| "download translations" / "memsource download" | Pull finished translations → convert to locale JSON → commit → optional PR |
| "translation status" / "memsource status" | Show Phrase job status per language |

State (last sprint, version, project ID) is stored in
[`.cursor/skills/i18n-memsource/state.json`](./state.json).
Expand Down Expand Up @@ -199,11 +199,11 @@ PO export does **not** upload English into every language blindly. For each lang
4. Leave new keys with empty `msgstr` for translators
5. **Post-export clear:** if `msgstr` still equals `msgid` (English placeholder left by `i18next-parser`), clear it to empty so Phrase marks it as needing translation

| Locale JSON value | msgstr uploaded to Phrase |
|-------------------|---------------------------|
| Real translation (e.g. Japanese) | Kept |
| Empty | Empty (needs translation) |
| English placeholder | Cleared to empty (needs translation) |
| Locale JSON value | msgstr uploaded to Phrase |
| -------------------------------- | ------------------------------------ |
| Real translation (e.g. Japanese) | Kept |
| Empty | Empty (needs translation) |
| English placeholder | Cleared to empty (needs translation) |

That is why you must run `npm run export-pos` (never hand-edit English-only POs).

Expand Down Expand Up @@ -282,20 +282,20 @@ done

## Common pitfalls

| Pitfall | What happens | Fix |
|---------|--------------|-----|
| `memsource` not on PATH | `command not found` | `export PATH="$HOME/Library/Python/3.9/bin:$PATH"` (or activate the memsource venv) |
| Login without exporting token | 401 `auth: not logged` on whoami/job list | `export MEMSOURCE_TOKEN=$(memsource auth login … -f json \| …)` |
| Comma-separated `-c uid,status,…` | CLI rejects columns as one name | Omit `-c`, or use `-c uid -c status -c target_lang` |
| Skip `zh-cn` symlink on upload | Chinese translations wiped in the Phrase project | Always `ln -sfn zh locales/zh-cn` before export/upload |
| Hand-build POs from English only | Existing ja/ko/fr/es/zh translations lost | Always use `npm run export-pos` |
| Leave English in msgstr | Phrase may treat those strings as already translated | Use current `export-pos` (includes `clear-english-msgstr.js`) |
| Trust download script's git clean check | Uncommitted `locales/` changes get overwritten | Run `git status -- locales/` yourself |
| Download before jobs complete | Incomplete locale overwrite | Check job status first |
| Pitfall | What happens | Fix |
| ---------------------------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `memsource` not on PATH | `command not found` | `export PATH="$HOME/Library/Python/3.9/bin:$PATH"` (or activate the memsource venv) |
| Login without exporting token | 401 `auth: not logged` on whoami/job list | `export MEMSOURCE_TOKEN=$(memsource auth login … -f json \| …)` |
| Comma-separated `-c uid,status,…` | CLI rejects columns as one name | Omit `-c`, or use `-c uid -c status -c target_lang` |
| Skip `zh-cn` symlink on upload | Chinese translations wiped in the Phrase project | Always `ln -sfn zh locales/zh-cn` before export/upload |
| Hand-build POs from English only | Existing ja/ko/fr/es/zh translations lost | Always use `npm run export-pos` |
| Leave English in msgstr | Phrase may treat those strings as already translated | Use current `export-pos` (includes `clear-english-msgstr.js`) |
| Trust download script's git clean check | Uncommitted `locales/` changes get overwritten | Run `git status -- locales/` yourself |
| Download before jobs complete | Incomplete locale overwrite | Check job status first |
| Re-download in a fresh git worktree without `node_modules` | PO download succeeds, then `po-to-i18n` fails with `Cannot find module 'minimist'` | In the worktree: `ln -s /path/to/main/repo/node_modules node_modules` or `npm install`, then re-run download / `po-to-i18n` |
| Give Memsource password/token to the agent | Credential exposure | Authenticate only in your shell; never paste tokens into chat |
| Forget to update `state.json` | Next download/status uses stale project ID | Update state after every upload |
| Upload without reviewing `npm run i18n` | Unexpected key churn in locale files | Always review `git diff -- locales/` first |
| Give Memsource password/token to the agent | Credential exposure | Authenticate only in your shell; never paste tokens into chat |
| Forget to update `state.json` | Next download/status uses stale project ID | Update state after every upload |
| Upload without reviewing `npm run i18n` | Unexpected key churn in locale files | Always review `git diff -- locales/` first |

---

Expand Down
9 changes: 0 additions & 9 deletions .eslintignore

This file was deleted.

104 changes: 0 additions & 104 deletions .eslintrc.json

This file was deleted.

8 changes: 7 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# Ignore artifacts:
dist/
node_modules/
i18n-scripts/
i18n-scripts/
coverage/
package-lock.json
**/gui-test-screenshots/
**/cypress-a11y-report.json
charts/
locales/
5 changes: 3 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"arrowParens": "always",
"endOfLine": "auto",
"printWidth": 100,
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"tabWidth": 2,
"semi": true
"trailingComma": "all"
}
7 changes: 4 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ webpack.config.ts # Webpack config with ConsoleRemotePlugin
Each view under `src/views/{resource}/` follows a consistent structure:

| Directory | Purpose |
|---------------|-----------------------------------------------------------------------|
| ------------- | --------------------------------------------------------------------- |
| `actions/` | Action provider hooks (delete, edit) registered as console extensions |
| `details/` | Detail page with tabbed views (details, YAML) |
| `form/` | Form-based create/edit using `react-hook-form` |
Expand Down Expand Up @@ -117,8 +117,9 @@ All routing uses `react-router` v7. Import `Link`, `useNavigate`, `useLocation`,
When reviewing changes in this repo:

- [ ] Import order follows `simple-import-sort` groups (run `npm run lint`)
- [ ] Formatting matches Prettier (run `npm run format:check`)
- [ ] All user-visible strings must use the `useNetworkingTranslation` hook or the `Trans` component; never hardcode
English text
English text
- [ ] New translatable strings have been extracted (`npm run i18n`) and locale files committed
- [ ] No `console.*` calls — use `networkConsole` from `@utils/utils/helpers`
- [ ] No hex colors in SCSS — use PatternFly CSS variables
Expand All @@ -128,4 +129,4 @@ When reviewing changes in this repo:
- [ ] Path aliases (`@utils/`, `@views/`, `@styles/`) used instead of deep relative imports
- [ ] Console SDK hooks used for K8s resource operations (not direct API calls)
- [ ] Component isolation — one component per file; single-use hooks stay co-located with their component, not in shared
`utils/hooks/`
`utils/hooks/`
4 changes: 2 additions & 2 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Each manifest declares:
The plugin manages these Kubernetes resource kinds:

| Resource | API Group | View Path |
|-----------------------------|---------------------------|------------------------------|
| --------------------------- | ------------------------- | ---------------------------- |
| Service | `v1` (core) | `src/views/services/` |
| Route | `route.openshift.io/v1` | `src/views/routes/` |
| Ingress | `networking.k8s.io/v1` | `src/views/ingresses/` |
Expand Down Expand Up @@ -121,7 +121,7 @@ The project uses Prow and CI Operator (`.ci-operator.yaml`):
## Key Dependencies

| Package | Purpose |
|--------------------------------------------------------|--------------------------------------------------|
| ------------------------------------------------------ | ------------------------------------------------ |
| `@openshift-console/dynamic-plugin-sdk` | Console integration (hooks, CRUD, UI primitives) |
| `@openshift-console/dynamic-plugin-sdk-webpack` | Webpack plugin for module federation |
| `@kubevirt-ui/kubevirt-api` | KubeVirt type definitions and model utilities |
Expand Down
Loading