# 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: ``` ... ``` Where: - `` identifies the bundle or shared context - `` identifies the part of the module using the translation - `` describes the text purpose - `` 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.. ``` 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 `.feature.` 4. **Is this text related to an entity or value object?** → Place in `.entity..` 5. **Is this text used in forms?** → `.form.` or `.form.` 6. **Is this text related to exports?** → `.export..` 7. **Is it related to filtering, searching or parameters?** → `.filter.` or → `.filter..` 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.. person.. ``` ## 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.