This commit is contained in:
Copilot 2026-01-12 17:34:38 +00:00 committed by GitHub
commit 5783209011
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 184 additions and 0 deletions

View file

@ -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:

24
docs/development/index.md Normal file
View file

@ -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)

View file

@ -0,0 +1,158 @@
---
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 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')
```
## 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.).
**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:
- `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
**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"
**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
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
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
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)