@contentrain/rules 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,293 @@
1
+ # Internationalization (i18n) Quality Rules
2
+
3
+ These rules govern translation and localization quality for all content managed through Contentrain.
4
+ Every rule applies whenever the project has more than one locale configured.
5
+
6
+ ---
7
+
8
+ ## 1. Translation Completeness
9
+
10
+ ### 1.1 Coverage Requirement
11
+
12
+ - Read `.contentrain/config.json` → `locales.supported` to determine the full list of supported locales.
13
+ - EVERY entry that exists in the source locale MUST have a corresponding entry in ALL supported target locales.
14
+ - Missing translations are deployment blockers. Treat a missing locale file as an error, not a warning.
15
+
16
+ ### 1.2 Dictionary Entries
17
+
18
+ - Every key present in the source locale file MUST exist in every target locale file.
19
+ - No partial dictionaries. If a new key is added, add it for ALL locales in the same operation.
20
+ - If the agent cannot produce a quality translation, insert the source-locale text and set status to `draft` — never leave the key absent.
21
+
22
+ ### 1.3 Document and Singleton Entries
23
+
24
+ - When creating a new document or singleton entry, create locale files for ALL supported locales.
25
+ - The source locale file is the reference. Target locale files must contain translations of every field.
26
+ - Required fields in the model must be populated in every locale — empty required fields are invalid.
27
+
28
+ ### 1.4 Completeness Verification
29
+
30
+ Before committing, run this check:
31
+
32
+ 1. List all entry IDs in the source locale directory.
33
+ 2. For each target locale, confirm the same set of IDs exists.
34
+ 3. For each entry, confirm all required fields have non-empty values.
35
+ 4. Report any gaps as errors.
36
+
37
+ ---
38
+
39
+ ## 2. Translation Quality
40
+
41
+ ### 2.1 Idiomatic Translation
42
+
43
+ - Translate MEANING, not words. Literal word-for-word translation produces unnatural text.
44
+ - EN: "It's raining cats and dogs" → TR: "Bardaktan bosanircasina yagmur yagiyor" (NOT "Kediler ve kopekler yagiyor")
45
+ - Sentence structure must follow target language grammar, not source language grammar.
46
+ - Read translated text aloud mentally — if it sounds unnatural, rewrite it.
47
+
48
+ ### 2.2 Machine Translation Artifacts
49
+
50
+ Detect and fix these common machine-translation problems:
51
+
52
+ - Overly literal translations that ignore idiom.
53
+ - Incorrect gender agreement (common in Romance, Slavic, Turkic languages).
54
+ - Wrong register/formality (e.g., using informal "du" in German business content).
55
+ - Untranslated fragments left in source language mid-sentence.
56
+ - Garbled word order that follows source language syntax.
57
+
58
+ ### 2.3 Tone Preservation
59
+
60
+ - If the source content is casual, the translation must be casual in the target language.
61
+ - If the source content is formal, the translation must use formal register.
62
+ - Check `context.json` → `conventions.tone` — it applies to ALL locales.
63
+ - Formality mapping varies by language:
64
+ - German: use "Sie" (formal) for professional content, "du" for casual.
65
+ - French: use "vous" (formal) by default, "tu" only if explicitly configured.
66
+ - Turkish: use "siz" (formal) for professional, "sen" for casual.
67
+ - Japanese: use desu/masu form for professional content.
68
+
69
+ ### 2.4 Technical Terms
70
+
71
+ - Keep technical terms in their original form if no widely accepted translation exists.
72
+ - Keep as-is: "API", "webhook", "SSL", "DNS", "SDK", "CLI", "URL".
73
+ - Translate if established: "database" → "Datenbank" (de), "browser" → "navegador" (es).
74
+ - Check `vocabulary.json` for approved translations of technical terms per locale.
75
+ - If `vocabulary.json` specifies a translation, use it. Do not override with a different translation.
76
+
77
+ ### 2.5 Brand Terms
78
+
79
+ - Brand terms from `vocabulary.json` → `brand_terms` must be used exactly as specified per locale.
80
+ - Some brand terms are never translated (product names, company names).
81
+ - Some brand terms have locale-specific variants — use the variant defined in vocabulary.
82
+
83
+ ---
84
+
85
+ ## 3. Cultural Adaptation
86
+
87
+ ### 3.1 Date Formats
88
+
89
+ Reference the target locale convention when writing date examples or references in content:
90
+
91
+ | Locale | Format | Example |
92
+ |---|---|---|
93
+ | en-US | MM/DD/YYYY | 03/15/2025 |
94
+ | en-GB | DD/MM/YYYY | 15/03/2025 |
95
+ | de, fr, tr, most EU | DD.MM.YYYY or DD/MM/YYYY | 15.03.2025 |
96
+ | ja, zh, ko | YYYY/MM/DD or YYYY年MM月DD日 | 2025/03/15 |
97
+ | ISO 8601 | YYYY-MM-DD | 2025-03-15 |
98
+
99
+ - Do not hardcode date strings. If content references a date, use locale-appropriate formatting.
100
+ - When in doubt, use ISO 8601 format.
101
+
102
+ ### 3.2 Number Formats
103
+
104
+ | Convention | Thousands | Decimal | Locales |
105
+ |---|---|---|---|
106
+ | Period-decimal | 1,000.00 | `.` | en, ja, zh, ko |
107
+ | Comma-decimal | 1.000,00 | `,` | de, fr, tr, es, pt, it, nl |
108
+ | Space-thousands | 1 000,00 | `,` | fr (formal), sv, fi, pl |
109
+
110
+ - Match the target locale convention when writing numbers in content.
111
+ - Currency values: always specify the currency code (USD, EUR, TRY). Never assume currency from locale alone.
112
+
113
+ ### 3.3 Units of Measurement
114
+
115
+ - en-US: imperial (miles, pounds, Fahrenheit) unless the context is scientific.
116
+ - Most other locales: metric (kilometers, kilograms, Celsius).
117
+ - Match the target locale convention. If content says "5 miles" in en-US, the de translation should say "8 km".
118
+
119
+ ### 3.4 Cultural Sensitivity
120
+
121
+ - Food, gestures, symbols, and colors carry different meanings across cultures.
122
+ - Do not reference culturally specific holidays as universal (e.g., "Thanksgiving" is US/Canada-specific).
123
+ - When referencing imagery in content, ensure descriptions are culturally appropriate for the target locale.
124
+ - Avoid idioms that do not translate — replace with locale-appropriate equivalents.
125
+
126
+ ---
127
+
128
+ ## 4. String Length Awareness
129
+
130
+ ### 4.1 Expansion Ratios
131
+
132
+ Expect these approximate expansion ratios from English source text:
133
+
134
+ | Target Language | Expansion | Notes |
135
+ |---|---|---|
136
+ | German | +30-40% | Compound words, longer sentences |
137
+ | Finnish | +30-40% | Agglutinative morphology |
138
+ | Dutch | +25-35% | Longer compound words |
139
+ | French | +15-25% | Articles, prepositions |
140
+ | Spanish | +15-25% | Longer verb forms |
141
+ | Portuguese | +15-25% | Similar to Spanish |
142
+ | Italian | +10-20% | Moderate expansion |
143
+ | Turkish | +10-20% | Suffixation expands words |
144
+ | Russian | +10-15% | Moderate expansion |
145
+ | Chinese (zh) | -30-50% | Fewer characters, wider glyphs |
146
+ | Japanese (ja) | -20-40% | Mixed scripts, compact |
147
+ | Korean (ko) | -10-20% | Syllable blocks |
148
+ | Arabic (ar) | -10-20% | Compact script, RTL |
149
+
150
+ ### 4.2 Field Constraints
151
+
152
+ - Check the model's `max` field constraint for every text field.
153
+ - The translated text MUST fit within the `max` character limit.
154
+ - If a translation exceeds the limit, rewrite it shorter. Do NOT truncate mid-word or mid-sentence.
155
+ - Test the longest expected language (usually German or Finnish) against all max constraints.
156
+
157
+ ### 4.3 UI String Considerations
158
+
159
+ - Button labels, menu items, and form labels have tight space constraints.
160
+ - German button text may need abbreviation or restructuring to fit.
161
+ - Verify that translated UI strings do not break layout assumptions.
162
+
163
+ ---
164
+
165
+ ## 5. Dictionary Key Naming
166
+
167
+ ### 5.1 Naming Convention
168
+
169
+ - Use semantic, hierarchical, dot-separated keys.
170
+ - GOOD: `auth.login.button`, `errors.404.title`, `nav.main.dashboard`
171
+ - BAD: `button1`, `text_3`, `label_top`, `str_47`
172
+ - Key names are always in English regardless of locale.
173
+ - Use lowercase with dots as separators. No spaces, no camelCase, no PascalCase in keys.
174
+
175
+ ### 5.2 Grouping
176
+
177
+ - Group keys by feature or domain, not by page or visual position.
178
+ - GOOD: `auth.login.button`, `auth.login.email_label`, `auth.login.error`
179
+ - BAD: `login_page.top_button`, `login_page.first_input`, `login_page.red_text`
180
+ - Top-level groups: `auth`, `nav`, `errors`, `forms`, `common`, `notifications`, `settings`.
181
+ - Add new groups only when existing groups do not fit.
182
+
183
+ ### 5.3 Consistency
184
+
185
+ - Similar concepts use similar key structures across features.
186
+ - `auth.login.button` and `auth.signup.button` — parallel structure.
187
+ - Do not use different naming patterns for the same concept.
188
+ - Before adding a new key, check existing keys for established patterns.
189
+
190
+ ---
191
+
192
+ ## 6. RTL Language Support
193
+
194
+ ### 6.1 RTL Locales
195
+
196
+ Flag these locales as right-to-left:
197
+
198
+ - Arabic (`ar`)
199
+ - Hebrew (`he`)
200
+ - Persian / Farsi (`fa`)
201
+ - Urdu (`ur`)
202
+ - Pashto (`ps`)
203
+ - Sindhi (`sd`)
204
+
205
+ ### 6.2 Content Rules for RTL
206
+
207
+ - Body text flows right-to-left. Do not force LTR markers in body content.
208
+ - Embedded elements that remain LTR: numbers, URLs, email addresses, code snippets, brand names in Latin script.
209
+ - Punctuation placement follows RTL rules: period at the left end of a sentence.
210
+ - Lists and bullet points align to the right margin.
211
+
212
+ ### 6.3 Bidirectional Text
213
+
214
+ - When RTL text contains LTR segments (e.g., a product name in English), ensure proper Unicode bidi handling.
215
+ - Do not manually insert Unicode directional markers (LRM, RLM) in content — leave that to the rendering layer.
216
+ - Test that mixed-direction content reads correctly in sequence.
217
+
218
+ ---
219
+
220
+ ## 7. Pluralization
221
+
222
+ ### 7.1 Plural Categories
223
+
224
+ Languages have different plural rule counts:
225
+
226
+ | Category | Languages | Plural Forms |
227
+ |---|---|---|
228
+ | No plurals | Chinese, Japanese, Korean, Vietnamese | 1 (`other`) |
229
+ | Two forms | English, German, Dutch, Spanish, Italian, Portuguese, Turkish | 2 (`one`, `other`) |
230
+ | Three forms | French, Brazilian Portuguese | 2-3 (`one`, `other`, sometimes `many`) |
231
+ | Multiple forms | Russian, Polish, Czech, Ukrainian | 3-4 (`one`, `few`, `many`, `other`) |
232
+ | Complex | Arabic | 6 (`zero`, `one`, `two`, `few`, `many`, `other`) |
233
+
234
+ ### 7.2 Dictionary Key Structure for Plurals
235
+
236
+ - Use CLDR plural categories as key suffixes:
237
+ - `items.zero` — zero items (where applicable)
238
+ - `items.one` — exactly one item
239
+ - `items.two` — exactly two items (Arabic)
240
+ - `items.few` — small numbers (language-specific rules)
241
+ - `items.many` — large numbers (language-specific rules)
242
+ - `items.other` — default/fallback (REQUIRED for every plural set)
243
+ - The `other` key is mandatory. It is the fallback for any count not covered by other categories.
244
+ - Only include the plural categories relevant to the target language.
245
+ - English: `items.one`, `items.other`
246
+ - Arabic: all six categories
247
+
248
+ ### 7.3 ICU Message Format
249
+
250
+ - When the project uses ICU message format, reference it correctly:
251
+ - `{count, plural, one {# item} other {# items}}`
252
+ - Do not invent custom pluralization logic. Use the established format.
253
+
254
+ ---
255
+
256
+ ## 8. Vocabulary Alignment
257
+
258
+ ### 8.1 Cross-Locale Vocabulary
259
+
260
+ - `vocabulary.json` must have entries for ALL supported locales.
261
+ - When adding a new canonical term, provide the translation for every supported locale.
262
+ - If a term has no natural translation, mark it as "keep original" in the vocabulary entry.
263
+
264
+ ### 8.2 Consistency Enforcement
265
+
266
+ - Every occurrence of a canonical term in every locale must match `vocabulary.json`.
267
+ - Run vocabulary checks across all locales, not just the source locale.
268
+ - If a translated term appears inconsistent (e.g., "Einstellungen" in one entry and "Konfiguration" in another for "Settings"), flag it and use the vocabulary-defined term.
269
+
270
+ ### 8.3 Adding New Terms
271
+
272
+ - Do not add new terms to `vocabulary.json` without human approval.
273
+ - When the agent encounters a term that should be canonical but is not in the vocabulary, flag it in the commit message or review notes.
274
+ - New terms must include: source term, translation for each locale, context/usage note.
275
+
276
+ ---
277
+
278
+ ## Validation Checklist
279
+
280
+ Before committing any multilingual content, verify:
281
+
282
+ - [ ] All supported locales have entries for every content item
283
+ - [ ] All required fields are populated in every locale
284
+ - [ ] No machine-translation artifacts (literal translations, wrong grammar)
285
+ - [ ] Tone matches source content in all target locales
286
+ - [ ] Technical terms follow `vocabulary.json` or are kept in original form
287
+ - [ ] Brand terms exactly match `vocabulary.json` per locale
288
+ - [ ] Translated text fits within field `max` constraints
289
+ - [ ] Date, number, and currency formats match target locale
290
+ - [ ] Dictionary keys are semantic, hierarchical, and in English
291
+ - [ ] Plural forms use correct CLDR categories for each language
292
+ - [ ] RTL locales are flagged and content follows RTL rules
293
+ - [ ] Vocabulary entries exist for all terms in all supported locales