From 01c368c42cf17cf8288ccd6b6b601a00a5069eed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:34:01 +0000 Subject: [PATCH 1/3] Initial plan From 0433651f6a2c17d6f94e0087f45110ab2305c0b8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:39:50 +0000 Subject: [PATCH 2/3] Add translation system documentation for contributors Co-authored-by: jbtronics <5410681+jbtronics@users.noreply.github.com> --- CONTRIBUTING.md | 2 + docs/development/index.md | 24 ++++ docs/development/translation.md | 231 ++++++++++++++++++++++++++++++++ 3 files changed, 257 insertions(+) create mode 100644 docs/development/index.md create mode 100644 docs/development/translation.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5994a115..402925f3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,6 +17,8 @@ If you want to start translation for a new language that does not have an entry Part-DB uses translation keys (e.g. part.info.title) that are sorted by their usage, so you will most likely have to lookup, how the key was translated in other languages (this is possible via the "Other languages" dropdown in the translation editor). +For detailed information about the translation system, including how to use type synonyms and placeholders, see the [Translation System Documentation](docs/development/translation.md). + ## Project structure Part-DB uses Symfony's recommended [project structure](https://symfony.com/doc/current/best_practices.html). Interesting folders are: diff --git a/docs/development/index.md b/docs/development/index.md new file mode 100644 index 00000000..1400c80e --- /dev/null +++ b/docs/development/index.md @@ -0,0 +1,24 @@ +--- +title: Development +layout: default +nav_order: 10 +has_children: true +--- + +# Development Documentation + +This section contains documentation for contributors and developers working on Part-DB. + +## Contents + +- [Translation System](translation.md) - Learn how translations and synonyms work in Part-DB + +## Getting Started + +For general contributing guidelines, see the [CONTRIBUTING.md](../../CONTRIBUTING.md) file in the root of the repository. + +## Additional Resources + +- [GitHub Repository](https://github.com/Part-DB/Part-DB-server) +- [Issue Tracker](https://github.com/Part-DB/Part-DB-server/issues) +- [Crowdin Translation Platform](https://part-db.crowdin.com/part-db) diff --git a/docs/development/translation.md b/docs/development/translation.md new file mode 100644 index 00000000..defb3d05 --- /dev/null +++ b/docs/development/translation.md @@ -0,0 +1,231 @@ +--- +title: Translation System +layout: default +parent: Development +nav_order: 1 +--- + +# Translation System for Contributors + +This document explains how Part-DB's translation system works and how contributors can effectively use it. + +## Overview + +Part-DB uses Symfony's translation system with XLIFF format files. Translations are managed through [Crowdin](https://part-db.crowdin.com/part-db), but understanding the system's features is important for contributors working on code or translations. + +## Basic Translation Approach + +Part-DB uses translation keys rather than translating English strings directly. For example: + +- Translation key: `part.info.title` +- English: "Part Information" +- German: "Bauteil-Informationen" + +This approach has several advantages: +- Keys remain stable even if the English text changes +- The same key can have different translations in different contexts +- Keys are organized hierarchically by feature/context + +### Using Translations in Code + +In PHP/Twig: +```twig +{{ 'part.info.title'|trans }} +``` + +In PHP: +```php +$translator->trans('part.info.title') +``` + +## Type Synonyms and Placeholders + +Part-DB includes a powerful synonym system that allows customizing the names of entity types (like "Category", "Part", "Manufacturer") throughout the interface. This is particularly useful for organizations that prefer different terminology. + +### How Synonyms Work + +Administrators can define custom names for entity types in the settings (Settings → Synonyms). These custom names are then automatically substituted throughout the application using translation placeholders. + +### Placeholder Syntax + +The synonym system uses special placeholders in translation strings that get replaced with the appropriate entity type name: + +| Placeholder | Meaning | Example Output (Default) | Example Output (with synonym) | +|------------|---------|-------------------------|------------------------------| +| `[Type]` | Singular, capitalized | "Category" | "Product Group" | +| `[[Type]]` | Plural, capitalized | "Categories" | "Product Groups" | +| `[type]` | Singular, lowercase | "category" | "product group" | +| `[[type]]` | Plural, lowercase | "categories" | "product groups" | + +Where `Type` is the element type name (e.g., `category`, `part`, `manufacturer`, etc.). + +### Available Element Types + +The following element types support synonyms: + +- `category` - Part categories +- `part` - Electronic parts/components +- `manufacturer` - Component manufacturers +- `supplier` - Component suppliers +- `storage_location` - Physical storage locations (also called `storelocation`) +- `footprint` - PCB footprints +- `attachment_type` - File attachment types +- `measurement_unit` - Units of measurement +- `currency` - Currencies +- `project` - Projects +- And many others (see `ElementTypes` enum in code) + +### Examples + +#### Basic Usage + +Translation string: +``` +"Click here to create a new [Category]" +``` + +Default output: +``` +"Click here to create a new Category" +``` + +With custom synonym (Category → "Product Type"): +``` +"Click here to create a new Product Type" +``` + +#### Multiple Placeholders + +Translation string: +``` +"This [part] belongs to [category] 'Electronics'" +``` + +Default output: +``` +"This part belongs to category 'Electronics'" +``` + +With custom synonyms: +``` +"This component belongs to product group 'Electronics'" +``` + +#### Plural Usage + +Translation string: +``` +"You have 5 [[part]] in 3 [[category]]" +``` + +Default output: +``` +"You have 5 parts in 3 categories" +``` + +With custom synonyms (Part → "Component", Category → "Group"): +``` +"You have 5 components in 3 groups" +``` + +#### Case Variations + +Translation string: +``` +"Select a [Category] to view its [[part]]" +``` + +This demonstrates: +- `[Category]` - Capitalized singular (starts sentence or emphasizes) +- `[[part]]` - Lowercase plural (mid-sentence) + +### Technical Implementation + +The synonym system is implemented through several components: + +1. **SynonymSettings** (`src/Settings/SynonymSettings.php`): Stores user-defined synonyms +2. **ElementTypeNameGenerator** (`src/Services/ElementTypeNameGenerator.php`): Generates localized labels +3. **RegisterSynonymsAsTranslationParametersListener** (`src/EventListener/RegisterSynonymsAsTranslationParametersListener.php`): Registers placeholders globally + +The system automatically: +- Generates placeholders for all element types at application startup +- Handles capitalization properly for different languages +- Falls back to default translations if no synonym is defined +- Caches placeholder values for performance + +### Guidelines for Using Synonyms in Translations + +When writing or updating translation strings: + +1. **Use synonyms for entity type references**: When referring to entity types like categories, parts, manufacturers, etc., use the synonym placeholders instead of hardcoding the type name. + + ✅ Good: `"Delete this [category]?"` + + ❌ Bad: `"Delete this category?"` + +2. **Match the case to context**: + - Use capitalized forms (`[Type]`, `[[Type]]`) at the start of sentences or for emphasis + - Use lowercase forms (`[type]`, `[[type]]`) in the middle of sentences + +3. **Choose singular vs. plural appropriately**: + - Use singular for single items: `"Create new [part]"` + - Use plural for multiple items or lists: `"Available [[part]]"` + +4. **Consistency**: Be consistent with placeholder usage across similar translation strings + +5. **Don't overuse**: Only use placeholders for actual entity type names. Don't use them for: + - Action verbs (use regular translations) + - Specific feature names + - UI element names that aren't entity types + +### Testing Synonyms + +To test how your translations work with synonyms: + +1. Go to Settings → Synonyms in Part-DB +2. Define custom synonyms for the types you're testing +3. Navigate to pages that use your translation strings +4. Verify the synonyms appear correctly with proper capitalization and plurality + +## Translation Parameters + +In addition to synonym placeholders, Part-DB uses standard Symfony translation parameters for dynamic values: + +``` +"You have %count% parts selected" +``` + +Parameters are passed when calling the translation: +```php +$translator->trans('parts.selected', ['%count%' => 5]) +``` + +Important: Parameters use `%paramName%` syntax, while synonym placeholders use `[Type]` or `[[Type]]` syntax. + +## Translation Files + +Translation files are located in the `translations/` directory and use XLIFF format: + +- `messages.en.xlf` - English translations +- `messages.de.xlf` - German translations +- `messages.{locale}.xlf` - Other languages + +The XLIFF format includes: +- Source key (translation key) +- Target (translated text) +- Notes (file locations where the key is used) + +## Best Practices + +1. **Use translation keys, not hardcoded text**: Always use translation keys for any user-facing text +2. **Organize keys hierarchically**: Use dots to namespace keys (e.g., `part.info.title`) +3. **Use synonym placeholders for entity types**: This gives administrators flexibility +4. **Test with different synonym configurations**: Ensure your text works with custom names +5. **Be consistent**: Follow existing patterns for similar functionality +6. **Check other languages**: Look at how similar keys are translated in other languages (via Crowdin's "Other languages" dropdown) + +## Resources + +- [Crowdin Part-DB Project](https://part-db.crowdin.com/part-db) +- [Symfony Translation Documentation](https://symfony.com/doc/current/translation.html) +- [Contributing Guide](../../CONTRIBUTING.md) From 1894d611fbd4abf489a80740d5cd59161509e245 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 7 Dec 2025 13:17:00 +0000 Subject: [PATCH 3/3] Address feedback: add trans/endtrans syntax, inflection note, reduce verbosity Co-authored-by: jbtronics <5410681+jbtronics@users.noreply.github.com> --- docs/development/translation.md | 113 ++++++-------------------------- 1 file changed, 20 insertions(+), 93 deletions(-) diff --git a/docs/development/translation.md b/docs/development/translation.md index defb3d05..f6e0b896 100644 --- a/docs/development/translation.md +++ b/docs/development/translation.md @@ -28,11 +28,16 @@ This approach has several advantages: ### Using Translations in Code -In PHP/Twig: +In Twig (short syntax): ```twig {{ 'part.info.title'|trans }} ``` +In Twig (block syntax for longer text): +```twig +{% trans %}part.info.title{% endtrans %} +``` + In PHP: ```php $translator->trans('part.info.title') @@ -59,6 +64,8 @@ The synonym system uses special placeholders in translation strings that get rep Where `Type` is the element type name (e.g., `category`, `part`, `manufacturer`, etc.). +**Note for inflected languages**: In languages like German where words are inflected (e.g., case declensions), synonyms should be defined in the nominative case (the standard/dictionary form). The placeholders will be substituted as-is, so translations need to be written to work with the nominative form. + ### Available Element Types The following element types support synonyms: @@ -77,67 +84,13 @@ The following element types support synonyms: ### Examples -#### Basic Usage +**Example 1**: `"Click here to create a new [Category]"` +- Default: "Click here to create a new Category" +- With synonym (Category → "Product Type"): "Click here to create a new Product Type" -Translation string: -``` -"Click here to create a new [Category]" -``` - -Default output: -``` -"Click here to create a new Category" -``` - -With custom synonym (Category → "Product Type"): -``` -"Click here to create a new Product Type" -``` - -#### Multiple Placeholders - -Translation string: -``` -"This [part] belongs to [category] 'Electronics'" -``` - -Default output: -``` -"This part belongs to category 'Electronics'" -``` - -With custom synonyms: -``` -"This component belongs to product group 'Electronics'" -``` - -#### Plural Usage - -Translation string: -``` -"You have 5 [[part]] in 3 [[category]]" -``` - -Default output: -``` -"You have 5 parts in 3 categories" -``` - -With custom synonyms (Part → "Component", Category → "Group"): -``` -"You have 5 components in 3 groups" -``` - -#### Case Variations - -Translation string: -``` -"Select a [Category] to view its [[part]]" -``` - -This demonstrates: -- `[Category]` - Capitalized singular (starts sentence or emphasizes) -- `[[part]]` - Lowercase plural (mid-sentence) +**Example 2**: `"You have 5 [[part]] in 3 [[category]]"` +- Default: "You have 5 parts in 3 categories" +- With synonyms (Part → "Component", Category → "Group"): "You have 5 components in 3 groups" ### Technical Implementation @@ -153,39 +106,13 @@ The system automatically: - Falls back to default translations if no synonym is defined - Caches placeholder values for performance -### Guidelines for Using Synonyms in Translations +### Guidelines for Using Synonyms -When writing or updating translation strings: - -1. **Use synonyms for entity type references**: When referring to entity types like categories, parts, manufacturers, etc., use the synonym placeholders instead of hardcoding the type name. - - ✅ Good: `"Delete this [category]?"` - - ❌ Bad: `"Delete this category?"` - -2. **Match the case to context**: - - Use capitalized forms (`[Type]`, `[[Type]]`) at the start of sentences or for emphasis - - Use lowercase forms (`[type]`, `[[type]]`) in the middle of sentences - -3. **Choose singular vs. plural appropriately**: - - Use singular for single items: `"Create new [part]"` - - Use plural for multiple items or lists: `"Available [[part]]"` - -4. **Consistency**: Be consistent with placeholder usage across similar translation strings - -5. **Don't overuse**: Only use placeholders for actual entity type names. Don't use them for: - - Action verbs (use regular translations) - - Specific feature names - - UI element names that aren't entity types - -### Testing Synonyms - -To test how your translations work with synonyms: - -1. Go to Settings → Synonyms in Part-DB -2. Define custom synonyms for the types you're testing -3. Navigate to pages that use your translation strings -4. Verify the synonyms appear correctly with proper capitalization and plurality +When writing translation strings: +- Use placeholders for entity types (✅ `"Delete this [category]?"` ❌ `"Delete this category?"`) +- Match case to context: capitalized (`[Type]`, `[[Type]]`) at sentence start, lowercase (`[type]`, `[[type]]`) mid-sentence +- Use singular for single items, plural for multiple items +- Only use for actual entity type names, not for actions or feature names ## Translation Parameters