{"id":29259570,"url":"https://github.com/RiskChallenger/translation-validation","last_synced_at":"2025-07-04T07:02:01.168Z","repository":{"id":39213794,"uuid":"342340327","full_name":"RiskChallenger/translation-validation","owner":"RiskChallenger","description":"Automatic validation messages for Angular forms in any language","archived":false,"fork":false,"pushed_at":"2025-06-19T09:46:18.000Z","size":4799,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-03T20:51:48.157Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://riskchallenger.github.io/translation-validation/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RiskChallenger.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-02-25T18:26:17.000Z","updated_at":"2025-06-28T23:22:23.000Z","dependencies_parsed_at":"2023-12-21T19:11:40.095Z","dependency_job_id":"86b22577-0ebd-44e6-9a23-2806a7173539","html_url":"https://github.com/RiskChallenger/translation-validation","commit_stats":{"total_commits":100,"total_committers":4,"mean_commits":25.0,"dds":0.5800000000000001,"last_synced_commit":"9636bf259f0317747b4da25dbdf2a10254a595c2"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/RiskChallenger/translation-validation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RiskChallenger%2Ftranslation-validation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RiskChallenger%2Ftranslation-validation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RiskChallenger%2Ftranslation-validation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RiskChallenger%2Ftranslation-validation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RiskChallenger","download_url":"https://codeload.github.com/RiskChallenger/translation-validation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RiskChallenger%2Ftranslation-validation/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263403375,"owners_count":23461218,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-04T07:01:09.431Z","updated_at":"2025-07-04T07:02:01.156Z","avatar_url":"https://github.com/RiskChallenger.png","language":"TypeScript","funding_links":[],"categories":["Third Party Components"],"sub_categories":["Form Validation"],"readme":"# Translation validation\n\n\u003e Automatic validation messages for Angular forms in any language\n\n[![GitHub Release](https://img.shields.io/github/v/release/riskchallenger/translation-validation?style=flat-square)](https://github.com/RiskChallenger/translation-validation/releases)\n[![MIT](https://img.shields.io/packagist/l/doctrine/orm.svg?style=flat-square)](https://github.com/RiskChallenger/translation-validation/blob/main/LICENSE)\n[![commitizen](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat-square)](https://commitizen.github.io/cz-cli/)\n[![PRs](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/RiskChallenger/translation-validation/blob/main/CONTRIBUTING.md)\n[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)\n\nWe got tired of having to write code to display validation messages whenever a form control was invalid.\nSo instead we wrote a library that automatically injects a component displaying the error message.\n\n## Features\n\n✅ Custom error component  \n✅ Show validation message on change, blur or submit  \n✅ Translates using [Transloco](https://ngneat.github.io/transloco/)  \n⚠️ WIP: translates using [ngx-translate](https://github.com/ngx-translate/core)\n\n## Table of Contents\n\n- [Blog posts](#blog-posts)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Versioning](#versioning)\n- [FAQ](#faq)\n\n# Blog posts\n\n- [Translation validation for Angular - automatic validation messages translated](https://dev.to/langstra/translation-validation-automatic-validation-messages-translated-17ng)\n\n# Installation\n\nFrom your project folder, run:\n\n```shell\nyarn add ngx-translation-validation\n```\n\nor\n\n```shell\nnpm install --save ngx-translation-validation\n```\n\nAlso add transloco to your project if you haven't done so yet. [Add transloco to your project](https://ngneat.github.io/transloco/docs/installation)\n\nAfter this, you will need to register the providers using `provideNgxTv()`\n\nThis command will import the `NgxTvModule.forRoot()` in your `AppModule`:\n\n```ts\nimport { provideNgxTv } from 'ngx-translation-validation';\n\nbootstrapApplication(AppComponent, {\n  providers: [provideNgxTv(/* Optionally you can provide a config here **/)],\n});\n```\n\n## Usage\n\nTo get started simply import the `NgxTvModule` in the module of the component you want to have validation messages.\n\n```ts\nimport { NgxTvModule } from 'ngx-translation-validation';\n\n@NgModule({\n  declarations: [UserComponent],\n  imports: [NgxTvModule],\n  bootstrap: [UserComponent],\n})\nexport class UserModule {}\n```\n\nAnd then every [formControlName] or [formControl] element will automatically show validation messages when it is invalid.\n\n```angular2html\n\n\u003cform [formGroup]=\"form\"\u003e\n  \u003cdiv class=\"form-group\"\u003e\n    \u003clabel for=\"name\"\u003eName\u003c/label\u003e\n    \u003cinput formControlName=\"name\" id=\"name\" type=\"text\"\u003e\n  \u003c/div\u003e\n\u003c/form\u003e\n```\n\n### Internationalization\n\nTo show the validation in the current language of the application we use [Transloco](https://ngneat.github.io/transloco/) by default. It translates a key to a string in the current language of the app. The keys for the validation generates by this packages have the following form:\n\n```ts\ntype.scope.controlName.error;\n```\n\n- `type` - Name of the validation messages type. Useful for specifying a directory for the validation messages (default: validation)\n- `scope` - Group several validation messages to a specific form/group (default: general)\n- `controlName` - Name of the control on which the validation error occurs\n- `error` - The name of the validation error that occurs\n\n\u003e [!NOTE]  \n\u003e If the parent of the control is a FormArray, the control name will be set to the name of the parent of the FormArray.\n\n\u003cdetails\u003e\n  \u003csummary\u003eMore on resolving control names\u003c/summary\u003e\n\n```js\nformBuilder.group({\n  name: ['', Validators.required], // When the control is in a group, use the key of the group, controlName -\u003e name\n  company: formBuilder.group({\n    address: ['', Validators.required], // Nesting of groups is ignored, only direct parent is considered, controlName -\u003e address\n  }),\n  cars: formBuilder.array([\n    formBuilder.group({\n      model: ['', Validators.required], // Group nested in array, only direct parent is considered, controlName -\u003e model\n    }),\n  ]),\n  colorPreferences: formBuilder.array([\n    ['', Validators.required], // Control nested in array, controlName is name of array, controlName -\u003e colorPreferences\n  ]),\n});\n```\n\nIf the name of a control cannot be found, a `ControlNameNotFoundError` will be thrown, **no validation error will be shown!**\n\n\u003c/details\u003e\n\nExamples\n\n```ts\nvalidation.general.name.required;\nvalidation.general.email.email;\n\nvalidation.organizationForm.name.required;\n```\n\n### Configuration\n\nTo customize the behavior of the plugin you can pass an object to the `forRoot()` method.\n\n```ts\nimport { provideNgxTv } from 'ngx-translation-validation';\n\nbootstrapApplication(AppComponent, {\n  providers: [\n    provideNgxTv({\n      type: 'validation', // default 'validation'\n      defaultScope: 'general', // default 'general'\n      invalidClass: 'invalid-input', // default undefined\n      submittedClass: 'form-submitted', // default 'ng-submitted'\n      errorsComponent: SomeErrorContainerComponent, // default NgxTvContainerComponent\n    }),\n  ],\n});\n```\n\n- `invalidClass` - Class that is added to a formControl element when the control is invalid. Can be used for custom styling when you do not want to use `ng-invalid` (default: undefined)\n- `submittedClass` - Class that is added to the formGroup element when it is submitted. Can be used in combination with ng-invalid to style elements when invalid and the form is submitted (default: 'ng-submitted')\n- `errorsComponent` - Component in which the error message is rendered. If you want to use a custom component, please sure to extend the default (default: `NgxTvContainerComponent`)\n\n#### Configure scope\n\nTo specify to what scope validation messages belong you can use the `ngxTvScope` directive.\n\n### Styling\n\nBy default, the ngx-tv-container-component gets injected right after the formControl element. So you html would look something like this:\n\n```html\n\u003cinput type=\"text\" /\u003e \u003cngx-tv-container-component\u003e\u003c/ngx-tv-container-component\u003e\n```\n\nBut if you'd like the container to appear in a parent of the controlForm you could specify the location of the container with the `ngxTvContainer` directive.\n\n```angular2html\n\n\u003cform [formGroup]=\"form\" ngxTvContainer\u003e\n  \u003cdiv class=\"form-group\"\u003e\n    \u003clabel for=\"name\"\u003eName\u003c/label\u003e\n    \u003cinput formControlName=\"name\" id=\"name\" type=\"text\"\u003e\n  \u003c/div\u003e\n  \u003cbutton type=\"submit\"\u003eSubmit\u003c/button\u003e\n\u003c/form\u003e\n\u003cngx-tv-container-component\u003e\u003c/ngx-tv-container-component\u003e // container component will be rendered here\n```\n\n## Contribute\n\nWe welcome you to contribute. This can be done by reporting issues or feature requests. Even better is to not only report issues or feature requests, but then also to pick those issues up yourself.\n\nPlease read [CONTRIBUTING.md](./CONTRIBUTING.md) for details on the process for submitting pull requests to us.\n\n## Versioning\n\n| Library version | Angular version |\n| :-------------: | :-------------: |\n|      14.x       |       \u003e16       |\n|      13.x       |    \u003e=13 \u003c16     |\n|       1.x       |      12.x       |\n\n\u003cdiv\u003eIcons made by \u003ca href=\"http://www.freepik.com/\" title=\"Freepik\"\u003eFreepik\u003c/a\u003e from \u003ca href=\"https://www.flaticon.com/\" title=\"Flaticon\"\u003ewww.flaticon.com\u003c/a\u003e\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRiskChallenger%2Ftranslation-validation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRiskChallenger%2Ftranslation-validation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRiskChallenger%2Ftranslation-validation/lists"}