diff --git a/collaborating/developing.md b/collaborating/developing.md index 8e2e6babc5..74398b416e 100644 --- a/collaborating/developing.md +++ b/collaborating/developing.md @@ -24,20 +24,26 @@ To begin, ensure you have network access. Then, you'll need the following gh repo clone IFRCGo/go-web-app #Github CLI ``` -2. Install the dependencies +2. Initialize submodules + + ```bash + git submodule update --init --recursive --remote + ``` + +3. Install the dependencies ```bash pnpm install ``` -3. Create a `.env` file in the `app` directory and add variables from [env.ts](https://github.com/IFRCGo/go-web-app/blob/develop/app/env.ts). Any variables marked with `.optional()` are not mandatory for setup and can be skipped. +4. Create a `.env` file in the `app` directory and add variables from [env.ts](https://github.com/IFRCGo/go-web-app/blob/develop/app/env.ts). Any variables marked with `.optional()` are not mandatory for setup and can be skipped. ```bash cd app touch .env ``` -4. Start the development server: +5. Start the development server: ```bash pnpm start:app @@ -46,7 +52,7 @@ To begin, ensure you have network access. Then, you'll need the following > \[!NOTE]\ > To work on a specific development task, ensure you have the backend setup appropriately and configured properly. -5. Create a new branch for your work. +6. Create a new branch for your work. The stable branch for IFRC GO is `develop`, and all PRs for deployment should be merged into it. ```bash @@ -60,7 +66,7 @@ To begin, ensure you have network access. Then, you'll need the following * Fix Branch: For bug fixes, create branches under `fix/issue-description`. * Chore Branch: For maintenance tasks, create branches under `chore/task-name`. -6. Once you're happy with your changes, add and commit them to your branch.If your workflow requires changesets (e.g., when changes will impact versioning or are part of a release), create one before committing. Then push the branch to origin. +7. Once you're happy with your changes, add and commit them to your branch. If your workflow requires changesets (e.g., when changes will impact versioning or are part of a release), create one before committing. Then push the branch to origin. ```bash # Stage all changes @@ -81,7 +87,7 @@ To begin, ensure you have network access. Then, you'll need the following > \[!NOTE]\ > Review the [Changesets documentation](./release.md#changesets) and the [versioning guidelines](./release.md#versioning-guidelines-for-ifrc-go-project) for more details on versioning and tracking changes. -7. Create a Pull Request. +8. Create a Pull Request. Please read the [Issues and Pull Requests](./issues-and-pull-requests.md) guide for further information. > \[!IMPORTANT]\ diff --git a/collaborating/repository-structure.md b/collaborating/repository-structure.md index 5a4e943695..9da53c8a48 100644 --- a/collaborating/repository-structure.md +++ b/collaborating/repository-structure.md @@ -19,7 +19,7 @@ The [app](../app/) directory contains the main codebase for the web application * [app/generated/](../app/generated/) contains the API endpoint type definitions generated by [openapi-typescript](https://github.com/openapi-ts/openapi-typescript). * [app/scripts/](../app/scripts/) contains scripts executed as part of the project. - * [app/scripts/translate/](../app/scripts/translate/) contains scripts for synchronizing translations between the application code and the server. + * [app/scripts/translatte/](../app/scripts/translatte/) contains scripts for synchronizing translations between the application code and the translation server. * [app/src/](../app/src/) houses the core web application code. * [app/src/App/](../app/src/App/) contains the base application logic for IFRC GO, including authentication handling, routing, and React context setup. @@ -56,4 +56,10 @@ The [packages/go-ui-storybook](../packages/go-ui-storybook/) directory contains The [nginx-serve](../nginx-serve) directory contains nginx config and helm charts to run the web application. -> NOTE: We need to add more information later. +### Submodules + +The repository uses the following git submodules: + +* [go-api/](../go-api/) contains the OpenAPI schema for the GO backend API. Used to generate TypeScript types via `openapi-typescript`. +* [go-risk-module-api/](../go-risk-module-api/) contains the OpenAPI schema for the GO risk module API. +* [cacheppuccino/](../cacheppuccino/) contains the OpenAPI schema for the cacheppuccino translation caching service. diff --git a/collaborating/technology.md b/collaborating/technology.md index 3f2e214b77..a29e24a5f9 100644 --- a/collaborating/technology.md +++ b/collaborating/technology.md @@ -18,8 +18,16 @@ The IFRC GO web application is built using [React](https://react.dev/) and [Vite * **Routing** * [React Router](https://www.npmjs.com/package/react-router-dom) for client-side routing -* **Excel Exports** +* **Rich Text Editing** + * [TinyMCE](https://www.tiny.cloud/) via [tinymce-react](https://www.npmjs.com/package/@tinymce/tinymce-react) for rich text input fields + +* **Business Intelligence** + * [powerbi-client](https://www.npmjs.com/package/powerbi-client) for embedding Power BI reports + +* **Excel and CSV I/O** * [exceljs](https://www.npmjs.com/package/exceljs) for generating and importing Excel files + * [xlsx](https://www.npmjs.com/package/xlsx) for reading Excel files + * [papaparse](https://www.npmjs.com/package/papaparse) for parsing CSV files * **Data Fetching** * [@togglecorp/toggle-request](https://www.npmjs.com/package/@togglecorp/toggle-request), a hooks-based request library @@ -33,5 +41,9 @@ The IFRC GO web application is built using [React](https://react.dev/) and [Vite * [Playwright](https://playwright.dev/) for end-to-end testing * [Vitest](https://vitest.dev/) for unit testing +* **Translation** + * [translatte](../app/scripts/translatte/) — custom CLI tooling for managing translation strings, generating migration files, and syncing with the translation server + * [cacheppuccino](../cacheppuccino/) — translation caching service (git submodule); provides an OpenAPI schema used to generate TypeScript types for translation API calls + * **Versioning and Changelog** * [Changesets](https://github.com/changesets/changesets) for managing versioning and generating changelogs diff --git a/collaborating/translation.md b/collaborating/translation.md index de9d9bc73f..15366c563c 100644 --- a/collaborating/translation.md +++ b/collaborating/translation.md @@ -2,4 +2,65 @@ The IFRC GO application supports the four official languages of the IFRC: English, French, Spanish, and Arabic. -TODO: Add documentation regarding translations +### Overview + +Translation strings are stored in `i18n.json` files co-located with each component or view (e.g. `app/src/views/Home/i18n.json`). These files are the source of truth for all translatable strings. A custom CLI tool called **translatte** (located at `app/scripts/translatte/`) manages the full lifecycle of translations: linting, generating migration files, and pushing strings to the translation server. + +At runtime the application fetches translations from the **cacheppuccino** service, a translation caching service whose endpoint is configured via the `APP_TRANSLATION_API_ENDPOINT` environment variable. + +### Adding or Changing Strings + +1. Edit the relevant `i18n.json` file alongside the component. +2. Lint the translation files to catch duplicates or formatting errors: + + ```bash + pnpm translatte lint ./src/**/i18n.json + ``` + +3. Generate a migration file that captures the diff between the current strings and the last recorded state: + + ```bash + pnpm translatte generate-migration ./src/translationMigrations ./src/**/i18n.json + ``` + + Or using the convenience script: + + ```bash + pnpm translatte:generate + ``` + +4. Commit the new migration file alongside your code changes. + +### Translatte CLI Reference + +All commands are run from within the `app/` workspace directory. + +| Command | Description | +|---|---| +| `translatte lint ` | Lint `i18n.json` files for duplicated strings. Pass `--fix` to auto-fix. | +| `translatte lint-migrations ` | Lint migration files for diverging migrations. | +| `translatte list-migrations ` | List all migration files. | +| `translatte generate-migration ` | Generate a new migration file from current translation files. | +| `translatte merge-migrations --from --to ` | Merge a range of migration files into one. | +| `translatte apply-migrations --source --destination ` | Apply pending migrations to a strings JSON file. | +| `translatte export-migration-to-excel ` | Export a migration file to XLSX for external translators. | +| `translatte push-strings-from-excel --api-url --auth-token ` | Push translated strings from an XLSX file to the GO API. | +| `translatte push-strings-from-excel-to-ifrc --api-url --api-key --application-id ` | Push translated strings from an XLSX file to the IFRC translation service. | +| `translatte push-migrations-to-go --api-url --auth-token ` | Push pending migrations directly to the GO API. | +| `translatte push-migrations-to-ifrc --api-url --api-key --application-id ` | Push pending migrations to the IFRC translation service. | +| `translatte export-server-strings ` | Export current server strings to an XLSX file. | +| `translatte clear-server-strings --api-url --auth-token ` | Remove all existing strings from the server. | + +### Environment Variables + +| Variable | Required | Description | +|---|---|---| +| `APP_TRANSLATION_API_ENDPOINT` | Yes | Base URL for the cacheppuccino translation caching service. | + +### Translation Workflow (Deployment) + +1. Developer adds/changes strings and generates a migration file (`translatte generate-migration`). +2. Migration file is committed and merged into `develop`. +3. During deployment, migrations are applied to produce an updated strings JSON (`translatte apply-migrations`). +4. The updated strings are pushed to the server (`translatte push-migrations-to-go` or `translatte push-migrations-to-ifrc`). +5. Translators receive an XLSX export (`translatte export-migration-to-excel`), translate the new strings, and the translated file is pushed back (`translatte push-strings-from-excel-to-ifrc`). diff --git a/packages/ui/package.json b/packages/ui/package.json index fa41dca580..329e8d5961 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -56,12 +56,11 @@ "dependencies": { "@ifrc-go/icons": "^2.0.1", "@togglecorp/fujs": "^2.1.1", - "jiti": "^2.5.1", "react-focus-on": "^3.9.1", "sanitize-html": "^2.11.0" }, "peerDependencies": { - "@ifrc-go/icons": "^1.3.1", + "@ifrc-go/icons": "^2.0.1", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -91,9 +90,8 @@ "postcss": "^8.5.3", "postcss-nested": "^7.0.2", "postcss-normalize": "^13.0.1", + "jiti": "^2.5.1", "postcss-preset-env": "^10.1.5", - "react-focus-on": "^3.9.1", - "sanitize-html": "^2.11.0", "stylelint": "^16.17.0", "stylelint-config-concentric": "^2.0.2", "stylelint-config-recommended": "^15.0.0", diff --git a/packages/ui/src/components/ChartContainer/index.tsx b/packages/ui/src/components/ChartContainer/index.tsx index 7e17d210ba..6b48e6a618 100644 --- a/packages/ui/src/components/ChartContainer/index.tsx +++ b/packages/ui/src/components/ChartContainer/index.tsx @@ -2,7 +2,7 @@ import { _cs } from '@togglecorp/fujs'; import styles from './styles.module.css'; -interface Props { +export interface Props { className?: string; children: React.ReactNode; chartData: { diff --git a/packages/ui/src/components/Checkbox/index.tsx b/packages/ui/src/components/Checkbox/index.tsx index 4f7ee4a666..f6defa2e51 100644 --- a/packages/ui/src/components/Checkbox/index.tsx +++ b/packages/ui/src/components/Checkbox/index.tsx @@ -1,4 +1,7 @@ -import { useCallback } from 'react'; +import { + useCallback, + useId, +} from 'react'; import { _cs } from '@togglecorp/fujs'; import InputError from '../InputError'; @@ -64,6 +67,7 @@ function Checkbox(props: Props) { [name, onChange, invertedLogic], ); + const inputId = useId(); const checked = invertedLogic ? !value : value; const className = _cs( @@ -77,12 +81,14 @@ function Checkbox(props: Props) { ); return ( -