localization
Instructions for managing localization and resource files in the AppProject .NET template. Covers adding translation keys to .resx files, resource key naming conventions, placeholder formatting, and maintaining consistency across en-US, pt-BR, and es-ES translations. Use when the user needs to add o
Install
mkdir -p .claude/skills/localization && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15086" && unzip -o skill.zip -d .claude/skills/localization && rm skill.zipInstalls to .claude/skills/localization
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Instructions for managing localization and resource files in the AppProject .NET template. Covers adding translation keys to .resx files, resource key naming conventions, placeholder formatting, and maintaining consistency across en-US, pt-BR, and es-ES translations. Use when the user needs to add or edit translations, resource keys, or localization support.About this skill
Localization & Resource Management
Overview
The template supports three languages:
en-US(English) —Resource.resxpt-BR(Brazilian Portuguese) —Resource.pt-BR.resxes-ES(Spanish) —Resource.es-ES.resx
Location: src/AppProject.Resources/
Both API and frontend consume resources via StringResource.GetStringByKey().
Resource Key Naming Conventions
Page Titles
<Module>_<EntityName>SummaryPage_Title
<Module>_<EntityName>FormPage_Title
Column Titles (grids)
<Module>_<EntityName>SummaryPage_<ColumnName>Column_Title
Fieldset Titles
<Module>_<EntityName>FormPage_<FieldsetName>Fieldset_Title
Field Labels
<Module>_<EntityName>FormPage_<FieldsetName>Fieldset_<FieldName>Field_Label
ID Display Field
<Module>_<EntityName>FormPage_<FieldsetName>Fieldset_IdField_Text
Validators
<Module>_<EntityName>FormPage_<FieldsetName>Fieldset_<FieldName>Field_Required
<Module>_<EntityName>FormPage_<FieldsetName>Fieldset_<FieldName>Field_InvalidLength
Menu Items
NavMenu_<Module>_Title
NavMenu_<Module>_<EntityName>_Text
Exception Messages
ExceptionCode_<Module>_<EntityName>_<ValidationName>
Permission Names
Permission_<Module>_<Action>_Name
Permission_<Module>_<Action>_Description
Adding New Resource Keys
When adding new keys, you MUST:
- Add to ALL three
.resxfiles — never leave translations missing - Preserve existing comments — each
.resxhas comment markers separating groups - Follow alphabetical order within each group
- Use the existing grouping/tabbing pattern — forms separated, validations and menu together
- Use
{{}}instead of{}for placeholder values that should be treated as literal text by the parser
Example Entry (Resource.resx — English)
<data name="General_CountryFormPage_Title" xml:space="preserve">
<value>Country</value>
</data>
<data name="General_CountryFormPage_GeneralFieldset_Title" xml:space="preserve">
<value>General</value>
</data>
<data name="General_CountryFormPage_GeneralFieldset_NameField_Label" xml:space="preserve">
<value>Name</value>
</data>
<data name="General_CountryFormPage_GeneralFieldset_NameField_Required" xml:space="preserve">
<value>Name is required.</value>
</data>
<data name="General_CountryFormPage_GeneralFieldset_NameField_InvalidLength" xml:space="preserve">
<value>Name must have a maximum of 200 characters.</value>
</data>
Example Entry (Resource.pt-BR.resx — Portuguese)
<data name="General_CountryFormPage_Title" xml:space="preserve">
<value>País</value>
</data>
<data name="General_CountryFormPage_GeneralFieldset_NameField_Label" xml:space="preserve">
<value>Nome</value>
</data>
<data name="General_CountryFormPage_GeneralFieldset_NameField_Required" xml:space="preserve">
<value>Nome é obrigatório.</value>
</data>
Example Entry (Resource.es-ES.resx — Spanish)
<data name="General_CountryFormPage_Title" xml:space="preserve">
<value>País</value>
</data>
<data name="General_CountryFormPage_GeneralFieldset_NameField_Label" xml:space="preserve">
<value>Nombre</value>
</data>
<data name="General_CountryFormPage_GeneralFieldset_NameField_Required" xml:space="preserve">
<value>El nombre es obligatorio.</value>
</data>
Placeholder Formatting
When you need to reserve future placeholder values in .resx files:
- Use
{{Value}}instead of{Value}— prevents the parser from trying to interpolate - Example:
The price is {{Price}}→ stored literally until template replaces it
Using Resources in Code
Blazor Components
@StringResource.GetStringByKey("General_CountryFormPage_Title")
With Interpolation
@StringResource.GetStringByKey("General_CountryFormPage_GeneralFieldset_IdField_Text", this.Model.Id)
In C# Code
StringResource.GetStringByKey("ExceptionCode_General_Country_DuplicateName")
Reusable Component Resource Keys
These keys are used by framework components and should NOT be duplicated:
| Key | Component | Purpose |
|---|---|---|
DataGridControl_NewButton_Text | DataGridControl | "New" button label |
DataGridControl_AddButton_Text | DataGridControl | "Add" button label |
DataGridControl_EditButton_Text | DataGridControl | "Edit" button label |
DataGridControl_OpenButton_Text | DataGridControl | "Open" button label |
DataGridControl_DeleteButton_Text | DataGridControl | "Delete" button label |
ModelFormControl_SaveButton_Text | ModelFormControl | "Save" button label |
ModelFormControl_ExecuteButton_Text | ModelFormControl | "Execute" button label |
ModelFormControl_CancelButton_Text | ModelFormControl | "Cancel" button label |
ModelFormControl_CloseButton_Text | ModelFormControl | "Close" button label |
Dialog_Confirm_Delete_Message | Shared | Delete confirmation message |
Language Selector
The frontend uses Blazored.LocalStorage to persist the selected language. The LanguageSelector.razor component handles switching.
Checklist
- Keys added to
Resource.resx(English) - Keys added to
Resource.pt-BR.resx(Portuguese) - Keys added to
Resource.es-ES.resx(Spanish) - Comments preserved in all
.resxfiles - Alphabetical order maintained within groups
- Placeholder values use
{{}}format - No duplicate keys