chore: heygermany customer project
This commit is contained in:
@@ -0,0 +1,351 @@
|
||||
# Translation System - CSV Guide
|
||||
|
||||
## What is this?
|
||||
|
||||
This guide explains how the translation CSV file works for the "Next Steps" section on candidate results pages. The system uses **translation tokens** to manage multilingual content efficiently.
|
||||
|
||||
---
|
||||
|
||||
## Understanding the CSV Structure
|
||||
|
||||
The translation CSV file has this structure:
|
||||
|
||||
| Token | EN | DE | UK | ... |
|
||||
|-------|----|----|----|----|
|
||||
| `default.getHelp.title` | Get Help | Hilfe erhalten | Отримати допомогу | ... |
|
||||
| `default.getHelp.subtitle` | Get free support... | Lassen Sie sich... | Отримайте... | ... |
|
||||
|
||||
**Key parts:**
|
||||
- **Token** (Column 1): The unique identifier for each piece of text
|
||||
- **EN, DE, UK, etc.** (Remaining columns): Translations for each language
|
||||
|
||||
---
|
||||
|
||||
## Token Naming Convention
|
||||
|
||||
Tokens follow a specific pattern: `{layer}.{step}.{property}`
|
||||
|
||||
### Structure Breakdown
|
||||
|
||||
```
|
||||
default.getHelp.title
|
||||
↓ ↓ ↓
|
||||
Layer Step Property
|
||||
```
|
||||
|
||||
**1. Layer** - Which candidate group this applies to:
|
||||
- `default` - Base layer for everyone
|
||||
- `nurse.default` - All nurses
|
||||
- `assistant.default` - All assistants
|
||||
- `nurse.allmet` - Specific nurse situation
|
||||
- `assistant.missinglicense` - Specific assistant situation
|
||||
|
||||
**2. Step** - Which of the 6 steps this text belongs to:
|
||||
- `getHelp` - Get Help step
|
||||
- `connect` - Connect with Employers step
|
||||
- `documents` - Prepare Your Documents step
|
||||
- `submit` - Submit Your Application step
|
||||
- `compensatory` - Complete a Compensatory Measure step
|
||||
- `german` - Improve Your German step
|
||||
|
||||
**3. Property** - What part of the step this is:
|
||||
- `title` - The step heading
|
||||
- `subtitle` - The description text
|
||||
- `costs` - Cost information text
|
||||
- `button` - Button text
|
||||
- `buttonImprove` / `buttonJoin` - Special buttons for connect step
|
||||
|
||||
---
|
||||
|
||||
## How the Layer System Works
|
||||
|
||||
The system uses **3 layers** that override each other, like stacking transparent sheets:
|
||||
|
||||
### Layer 1: `default.*` (Base Layer)
|
||||
|
||||
This is the foundation. Every step should have complete translations here.
|
||||
|
||||
**Example tokens:**
|
||||
```
|
||||
default.submit.title
|
||||
default.submit.subtitle
|
||||
default.submit.costs
|
||||
default.submit.button
|
||||
```
|
||||
|
||||
**When to use:** These apply to ALL candidates unless overridden by a more specific layer.
|
||||
|
||||
---
|
||||
|
||||
### Layer 2: `{role}.default.*` (Role Layer)
|
||||
|
||||
Changes text for **all candidates of a specific role** (nurse/assistant/helper).
|
||||
|
||||
**Example tokens:**
|
||||
```
|
||||
assistant.default.submit.subtitle
|
||||
assistant.default.submit.costs
|
||||
```
|
||||
|
||||
**What happens:**
|
||||
- `assistant.default.submit.subtitle` replaces `default.submit.subtitle` for ALL assistants
|
||||
- But `default.submit.title` still shows (not overridden)
|
||||
- But `default.submit.button` still shows (not overridden)
|
||||
|
||||
---
|
||||
|
||||
### Layer 3: `{role}.{situation}.*` (Specific Situation Layer)
|
||||
|
||||
Changes text for **one specific candidate situation** only.
|
||||
|
||||
**Example tokens:**
|
||||
```
|
||||
assistant.missinglicense.submit.subtitle
|
||||
```
|
||||
|
||||
**What happens:**
|
||||
- `assistant.missinglicense.submit.subtitle` replaces the subtitle for assistants missing their license
|
||||
- `assistant.default.submit.costs` still applies (from Layer 2)
|
||||
- `default.submit.title` still applies (from Layer 1)
|
||||
- `default.submit.button` still applies (from Layer 1)
|
||||
|
||||
---
|
||||
|
||||
## Real Example: How Tokens Stack
|
||||
|
||||
**Scenario:** A "Nursing Assistant without a license" views the "Submit Your Application" step.
|
||||
|
||||
**The system looks for tokens in this order:**
|
||||
|
||||
1. **Check Layer 3** (most specific):
|
||||
- `assistant.missinglicense.submit.title` → Not found ❌
|
||||
- `assistant.missinglicense.submit.subtitle` → Found ✅ "First upload your license..."
|
||||
- `assistant.missinglicense.submit.costs` → Not found ❌
|
||||
- `assistant.missinglicense.submit.button` → Not found ❌
|
||||
|
||||
2. **Check Layer 2** (role-specific):
|
||||
- `assistant.default.submit.title` → Not found ❌
|
||||
- `assistant.default.submit.subtitle` → Not needed (found in Layer 3)
|
||||
- `assistant.default.submit.costs` → Found ✅ "Cost: 150-250€"
|
||||
- `assistant.default.submit.button` → Not found ❌
|
||||
|
||||
3. **Check Layer 1** (default):
|
||||
- `default.submit.title` → Found ✅ "Submit Your Application"
|
||||
- `default.submit.subtitle` → Not needed (found in Layer 3)
|
||||
- `default.submit.costs` → Not needed (found in Layer 2)
|
||||
- `default.submit.button` → Found ✅ "Learn how to apply"
|
||||
|
||||
**Final Result:**
|
||||
- Title: "Submit Your Application" ← from `default.submit.title`
|
||||
- Subtitle: "First upload your license..." ← from `assistant.missinglicense.submit.subtitle`
|
||||
- Costs: "Cost: 150-250€" ← from `assistant.default.submit.costs`
|
||||
- Button: "Learn how to apply" ← from `default.submit.button`
|
||||
|
||||
---
|
||||
|
||||
## Available Steps & Properties
|
||||
|
||||
### The 6 Steps
|
||||
|
||||
Every next-steps journey can have these steps (use camelCase in tokens):
|
||||
|
||||
| Token Name | Display Name |
|
||||
|------------|--------------|
|
||||
| `getHelp` | Get Help |
|
||||
| `connect` | Connect with Employers |
|
||||
| `documents` | Prepare Your Documents |
|
||||
| `submit` | Submit Your Application |
|
||||
| `compensatory` | Complete a Compensatory Measure |
|
||||
| `german` | Improve Your German |
|
||||
|
||||
### Properties for Each Step
|
||||
|
||||
| Property | What it is | Example Token |
|
||||
|----------|-----------|---------------|
|
||||
| `title` | Step heading | `default.getHelp.title` |
|
||||
| `subtitle` | Description text | `default.getHelp.subtitle` |
|
||||
| `costs` | Cost information | `default.getHelp.costs` |
|
||||
| `button` | Button text | `default.getHelp.button` |
|
||||
| `buttonImprove` | Special button (connect only) | `default.connect.buttonImprove` |
|
||||
| `buttonJoin` | Special button (connect only) | `default.connect.buttonJoin` |
|
||||
|
||||
---
|
||||
|
||||
## Available Layers (All Valid Token Prefixes)
|
||||
|
||||
### Global Layer
|
||||
- `default` - Base for everyone
|
||||
|
||||
### Role Layers
|
||||
- `nurse.default` - Shared by all nurse situations
|
||||
- `assistant.default` - Shared by all assistant situations
|
||||
- `helper.default` - Shared by all helper situations
|
||||
|
||||
### Specific Situation Layers
|
||||
|
||||
**Nurses:**
|
||||
- `nurse.allmet`
|
||||
- `nurse.missinglicense`
|
||||
- `nurse.missinglicenseandaccreditation`
|
||||
|
||||
**Assistants:**
|
||||
- `assistant.allmet`
|
||||
- `assistant.missinglicense`
|
||||
- `assistant.missinglicenseandaccreditation`
|
||||
|
||||
**Helpers:**
|
||||
- Only uses `helper.default` (no specific situations)
|
||||
|
||||
---
|
||||
|
||||
## Dynamic Placeholders
|
||||
|
||||
Some translations can include placeholders that get replaced with actual data:
|
||||
|
||||
| Placeholder | Replaced with | Example |
|
||||
|-------------|---------------|---------|
|
||||
| `{currentLevel}` | Candidate's current German level | A1, B1, B2, etc. |
|
||||
| `{requiredLevel}` | Required German level | B1, B2, etc. |
|
||||
|
||||
**Example translation:**
|
||||
```
|
||||
default.german.subtitle = "You're currently at {currentLevel} — almost there! To gain full recognition, you'll need to improve your German to {requiredLevel} level."
|
||||
```
|
||||
|
||||
**Becomes:**
|
||||
```
|
||||
"You're currently at A2 — almost there! To gain full recognition, you'll need to improve your German to B2 level."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rules for Adding Translations
|
||||
|
||||
### 1. Always Fill Out the `default.*` Layer Completely
|
||||
|
||||
The base layer should have ALL properties for ALL steps. This ensures there's always a fallback.
|
||||
|
||||
**Required tokens for each step:**
|
||||
```
|
||||
default.{stepName}.title
|
||||
default.{stepName}.subtitle
|
||||
default.{stepName}.costs
|
||||
default.{stepName}.button
|
||||
```
|
||||
|
||||
### 2. Only Add Role/Situation Tokens When You Need to Change Something
|
||||
|
||||
If assistant costs are different, add:
|
||||
```
|
||||
assistant.default.submit.costs
|
||||
```
|
||||
|
||||
Don't add:
|
||||
```
|
||||
assistant.default.submit.title ← Not needed if same as default
|
||||
assistant.default.submit.button ← Not needed if same as default
|
||||
```
|
||||
|
||||
### 3. Use Consistent Naming
|
||||
|
||||
- Steps use camelCase: `getHelp`, `connect`, `documents`
|
||||
- Properties use camelCase: `title`, `subtitle`, `buttonImprove`
|
||||
- Layers use lowercase with dots: `assistant.default`, `nurse.allmet`
|
||||
|
||||
### 4. Add All Languages for Each Token
|
||||
|
||||
Every token row must have translations for all supported languages (EN, DE, UK, TL, TR, BS, SQ, VI, ES, HI, AR).
|
||||
|
||||
---
|
||||
|
||||
## Common Scenarios
|
||||
|
||||
### Scenario 1: Change just the subtitle for all assistants
|
||||
|
||||
**Add one token:**
|
||||
```
|
||||
assistant.default.submit.subtitle
|
||||
```
|
||||
|
||||
All other properties (title, costs, button) will fall through from `default.*`
|
||||
|
||||
---
|
||||
|
||||
### Scenario 2: Change subtitle for one specific situation
|
||||
|
||||
**Add one token:**
|
||||
```
|
||||
nurse.missinglicense.submit.subtitle
|
||||
```
|
||||
|
||||
Everything else comes from `nurse.default.*` (if exists) or `default.*`
|
||||
|
||||
---
|
||||
|
||||
### Scenario 3: Assistants have different costs and different process
|
||||
|
||||
**Add two tokens:**
|
||||
```
|
||||
assistant.default.submit.subtitle ← Changed process description
|
||||
assistant.default.submit.costs ← Different price
|
||||
```
|
||||
|
||||
Title and button stay from `default.*`
|
||||
|
||||
---
|
||||
|
||||
### Scenario 4: One situation needs urgent warning
|
||||
|
||||
**Add one token:**
|
||||
```
|
||||
assistant.missinglicenseandaccreditation.submit.subtitle
|
||||
```
|
||||
|
||||
This overrides even `assistant.default.submit.subtitle` for this specific situation.
|
||||
|
||||
---
|
||||
|
||||
## Why This System?
|
||||
|
||||
### Without this system:
|
||||
- 7 candidate situations × 6 steps × 4 properties = **168 translations per language**
|
||||
- Lots of duplication
|
||||
- Hard to make global changes
|
||||
|
||||
### With this system:
|
||||
- Base layer: ~24 translations (6 steps × 4 properties)
|
||||
- Role overrides: ~10 translations (only what's different)
|
||||
- Situation overrides: ~5 translations (only what's specific)
|
||||
- **Total: ~39 translations per language** (77% less!)
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference: Token Format
|
||||
|
||||
```
|
||||
{layer}.{step}.{property}
|
||||
↓ ↓ ↓
|
||||
(role. (camel (camel
|
||||
situation) Case) Case)
|
||||
|
||||
Examples:
|
||||
default.getHelp.title
|
||||
assistant.default.submit.costs
|
||||
nurse.missinglicense.documents.subtitle
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Checking Your Work
|
||||
|
||||
To verify a token will work correctly:
|
||||
|
||||
1. **Check the layer exists** in the "Available Layers" section above
|
||||
2. **Check the step name** is one of the 6 available steps (camelCase)
|
||||
3. **Check the property** is one of: title, subtitle, costs, button, buttonImprove, buttonJoin
|
||||
4. **Ensure all languages have translations** for that token
|
||||
|
||||
**Valid token:** ✅ `assistant.default.submit.costs`
|
||||
**Invalid token:** ❌ `assistant.submit.costs` (missing `.default` or situation)
|
||||
**Invalid token:** ❌ `default.Submit.costs` (should be `submit` not `Submit`)
|
||||
**Invalid token:** ❌ `default.submit.price` (should be `costs` not `price`)
|
||||
Reference in New Issue
Block a user