In this guide your will learn how to to make @ngx-formly
validation messages and labels translatable when using @ngx-translate
translation service.
What we want to achieve
- Create a namespace/group in our i18n translations file containing the error messages for formly validation.
- Inject
TranslateService
toFORMLY_CONFIG
provider. - Use the
TranslateService.stream()
method to provide observable translation keys for our messages. - Extend formly to use a
registerTranslateExtension
factory for our i18n extension.
Set up Formly module
In this example, I have created a standalone module called ClientFormlyModule
just for formly. This way, we can import this module inheriting the settings we set up only once. This generally a good practice and decouples your modules for when you have multiple angular apps in your project.
First let's take a look at ClientFormlyModule
.
...
import { FormlyModule, FORMLY_CONFIG } from '@ngx-formly/core';
@NgModule({
declarations: [],
imports: [
CommonModule,
ReactiveFormsModule,
FormlyModule.forRoot(),
FormlyBootstrapModule, // Optional
TranslateModule.forChild(),
],
providers: [
// Provide `FORMLY_CONFIG` with our settings
{
provide: FORMLY_CONFIG,
multi: true,
useFactory: registerTranslateExtension,
// Inject the `TranslateService` into the factory
deps: [TranslateService],
},
],
exports: [FormlyModule],
})
export class ClientFormlyModule {}
Notice that in the providers
we inject a factory formlyConfig
which I will explain next. Notice also that we need the TranslateService
as a dependency as well. This makes the instance of TranslateService
alliable to our injected method formlyConfig
.
The translations file
Depending on how you decided to setup @ngx-translate
you might have something similar to this.
export const en_US = {
FORM: {
VALIDATION: {
REQUIRED: "{{fieldName}} cannot be empty",
EMAIL: "Please enter a valid email address",
},
},
};
The idea is to have a namespace/group here to organize the translations for your validation messages.
Create the formlyConfig
factory function
When we set up the ClientFormlyModule
we specifically told formly to use a factory for it's FORMLY_CONFIG
and inject the TranslateService
as a dependency.
Therefore we now need to create a method that will take TranslateService
as an argument and return ConfigOption
interface (used for formly config)
import { ConfigOption, FormlyFieldConfig } from "@ngx-formly/core";
import { TranslateService } from "@ngx-translate/core";
export function formlyConfig(t: TranslateService): ConfigOption {
return {
validationMessages: [
{
name: "required",
message(err: Error, field: FormlyFieldConfig) {
return t.stream("FORM.VALIDATION.REQUIRED", {
fieldName: field?.templateOptions?.label,
});
},
},
{
name: "email",
message() {
return t.stream("FORM.VALIDATION.EMAIL");
},
},
],
validators: [],
};
}
That's it! Now formly is aware of our TranslateService
and will generate the correct i18n messages for your validation messages.