# Translation Key Directives

These directives are meant to ensure better consistency across bundles, avoid duplication, and make keys more predictable.

## General Principles

1. **Use lowercase snake_case for all keys**

2. **Use dot-separated namespaces**
   The dot is used to reflect:
    - bundle
    - feature
    - sub-feature
    - key type

3. **Do not use spaces in keys**

4. **Avoid duplicating the same text in multiple places**
   When a translation is needed, try a search for the translation value first and see if it exists elsewhere

5. **If a key is used across multiple bundles, it must live in ChillMainBundle.**

6. **If a key is used across multiple bundles and is a generic term, it must be placed in the `common` namespace.**

## Key Structure

We use the following structure:

```
<scope>.<feature>.<sub-feature>.<key-type>
```

Where:

- `<scope>` identifies the bundle or shared context
- `<feature>` identifies the part of the module using the translation
- `<element>` describes the text purpose
- `<subelement>` for a multi-level element (e.g., activity.export.person.count.description)

### Examples of scopes

- `activity` — ChillActivityBundle
- `person` — ChillPersonBundle
- `common` — neutral shared translation values

## Naming Scopes

### 1. Bundle-specific keys

For most things inside a bundle:

```
activity.<feature>.<element>
```

Example:

```
activity.form.save
activity.list.title
activity.entity.type
activity.menu.activities
activity.controller.success_created
```

### 2. Shared UI elements (buttons, labels, generic text)

These belong in the `common` namespace in ChillMainBundle:

```
common.save
common.delete
common.edit
common.filter
common.duration_time
```

## Translation Workflow

Use the following workflow when deciding where a key belongs:

1. **Is this text used in more than one bundle?**
   → Place in `main` or `common`

2. **Is this text generic UI (button, label, pagination, yes/no)?**
   → Place in `common`

3. **Is this text specific to one bundle and one feature?**
   → Place in `<bundle>.feature.<element>`

4. **Is this text related to an entity or value object?**
   → Place in `<bundle>.entity.<entityname>.<field>`

5. **Is this text used in forms?**
   → `<bundle>.form.<field>` or `<bundle>.form.<action>`

6. **Is this text related to exports?**
   → `<bundle>.export.<feature>.<column>`

7. **Is it related to filtering, searching or parameters?**
   → `<bundle>.filter.<name>` or
   → `<bundle>.filter.<feature>.<field>` for nested filters

## Examples Based on Translations Within ChillActivityBundle

Below are concrete examples from `ChillActivityBundle`, refactored according to the guidelines.

### General activity keys

Instead of scattered keys like:

```
Show the activity
Edit the activity
Activity
Duration time
...
```

We use:

```
activity.general.show
activity.general.edit
activity.general.title
activity.general.duration
activity.general.travel_time
activity.general.attendee
activity.general.remark
activity.general.no_comments
```

### Forms

Instead of keys like:

```
Activity creation
Save activity
Reset form
Choose a type
```

Use:

```
activity.form.title_create
activity.form.save
activity.form.reset
activity.form.choose_type
activity.form.choose_duration
```

Long lists (like durations) should be grouped:

```
activity.form.duration.5min
activity.form.duration.10min
activity.form.duration.15min
activity.form.duration.1h
activity.form.duration.1h30
activity.form.duration.2h
...
```

### Entities

Entity fields should follow:

```
activity.entity.activity.date
activity.entity.activity.comment
activity.entity.activity.deleted
activity.entity.location.name
activity.entity.location.type
```

### Controller messages

Instead of strings as keys:

```
'Success : activity created!'
'The form is not valid. The activity has not been created !'
```

Use:

```
activity.controller.success_created
activity.controller.error_invalid_create
activity.controller.success_updated
activity.controller.error_invalid_update
```

### Roles

Access control keys should be:

```
activity.role.create
activity.role.update
activity.role.see
activity.role.see_details
activity.role.delete
activity.role.stats
activity.role.list
```

### Admin

```
activity.admin.configuration
activity.admin.types
activity.admin.reasons
activity.admin.reason_category
activity.admin.presence
```

### CRUD

```
activity.crud.type.title_new
activity.crud.type.title_edit
activity.crud.presence.title_new
```

### Activity Reason

```
activity.reason.list
activity.reason.create
activity.reason.active
activity.reason.category
activity.reason.entity_title
```

### Exports

Group them logically:

```
activity.export.person.count.title
activity.export.person.count.description
activity.export.person.count.header

activity.export.period.sum_duration.title
activity.export.period.sum_duration.description
activity.export.period.sum_duration.header
```

### Filters

Use hierarchical filters:

```
activity.filter.by_reason
activity.filter.by_type
activity.filter.by_date
activity.filter.by_location
activity.filter.by_sent_received
activity.filter.by_user
```

### Aggregators

```
activity.aggregator.reason.by_category
activity.aggregator.reason.level
activity.aggregator.user.by_scope
activity.aggregator.user.by_job
```

## Global/Shared Keys

Keys like the following **must not be redeclared** in each bundle:

- First name
- Last name
- Username
- ID
- Type
- Duration
- Comment
- Date
- Location
- Present / Not present
- Add / Edit / Delete / Save / Update

These belong in `common` or `main`:

```
common.firstname
common.lastname
common.username
common.id
common.type
common.comment
common.date
common.location
common.present
common.absent
common.add
common.edit
common.delete
common.save
common.update
```

## Naming Directives Summary

- **snake_case**
- **namespaced with dots**
- **bundle prefix for bundle-specific concepts**
- **common or main for shared concepts**
- **avoid free-floating keys (without namespace)**
- **reuse common keys wherever possible**

## Migration Strategy (Optional)

To apply this structure progressively:

1. New keys must follow these guidelines.
2. Existing keys may remain as-is until refactored.
3. When refactoring:
    - Move cross-bundle keys to ChillMainBundle and possible `common` namespace.
    - Replace duplicated keys with shared ones.

---

# Avoiding Duplicate Translations

## 1. Use Shared Namespaces

Two namespaces must be used for shared translations:

- `common.*` — generic UI concepts (save, delete, date, name, etc.)

If a translation may be reused in multiple bundles, it must be placed in the `common` namespace or in ChillMainBundle.

## 2. Bundle-Specific Keys

Keys belonging only to one bundle or one feature are namespaced inside that bundle:

```
activity.<feature>.<element>
person.<feature>.<element>
```

## 3. Search Before Creating

Before adding a new translation key, developers must:

1. For common translations like "enregistrer/opslaan" look in the `common` namespace.
2. Search in Loco or translations for existing values.

If a suitable key exists, reuse it.

## 4. Only Create a New Key When Necessary

Create a new key only when the text is:

- specific to the bundle
- specific to the feature
- not reusable elsewhere

## 5. Progressive Cleanup

Old duplicates may remain temporarily. When updating code in an area, clean duplicate values by moving them into `common` or `main`.

## General Workflow

- **Reuse shared keys** within `common` namespace.
- **Search before creating** new keys.
- **Namespace bundle-specific keys** under their bundle.
- **Refactor progressively** when touching old code.
