@harness-engineering/cli 1.7.0 → 1.8.1

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.
Files changed (187) hide show
  1. package/dist/agents/personas/documentation-maintainer.yaml +3 -1
  2. package/dist/agents/personas/performance-guardian.yaml +23 -0
  3. package/dist/agents/skills/claude-code/align-documentation/SKILL.md +13 -0
  4. package/dist/agents/skills/claude-code/cleanup-dead-code/SKILL.md +25 -1
  5. package/dist/agents/skills/claude-code/cleanup-dead-code/skill.yaml +5 -2
  6. package/dist/agents/skills/claude-code/detect-doc-drift/SKILL.md +12 -0
  7. package/dist/agents/skills/claude-code/enforce-architecture/SKILL.md +48 -1
  8. package/dist/agents/skills/claude-code/enforce-architecture/skill.yaml +5 -2
  9. package/dist/agents/skills/claude-code/harness-accessibility/SKILL.md +7 -0
  10. package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +11 -3
  11. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +81 -11
  12. package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +2 -0
  13. package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +487 -234
  14. package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +15 -2
  15. package/dist/agents/skills/claude-code/harness-codebase-cleanup/SKILL.md +226 -0
  16. package/dist/agents/skills/claude-code/harness-codebase-cleanup/skill.yaml +64 -0
  17. package/dist/agents/skills/claude-code/harness-dependency-health/SKILL.md +35 -6
  18. package/dist/agents/skills/claude-code/harness-docs-pipeline/SKILL.md +460 -0
  19. package/dist/agents/skills/claude-code/harness-docs-pipeline/skill.yaml +69 -0
  20. package/dist/agents/skills/claude-code/harness-execution/SKILL.md +73 -8
  21. package/dist/agents/skills/claude-code/harness-execution/skill.yaml +1 -0
  22. package/dist/agents/skills/claude-code/harness-hotspot-detector/SKILL.md +32 -6
  23. package/dist/agents/skills/claude-code/harness-i18n/SKILL.md +484 -0
  24. package/dist/agents/skills/claude-code/harness-i18n/skill.yaml +54 -0
  25. package/dist/agents/skills/claude-code/harness-i18n-process/SKILL.md +388 -0
  26. package/dist/agents/skills/claude-code/harness-i18n-process/skill.yaml +43 -0
  27. package/dist/agents/skills/claude-code/harness-i18n-workflow/SKILL.md +512 -0
  28. package/dist/agents/skills/claude-code/harness-i18n-workflow/skill.yaml +53 -0
  29. package/dist/agents/skills/claude-code/harness-impact-analysis/SKILL.md +35 -6
  30. package/dist/agents/skills/claude-code/harness-integrity/SKILL.md +17 -1
  31. package/dist/agents/skills/claude-code/harness-knowledge-mapper/SKILL.md +46 -5
  32. package/dist/agents/skills/claude-code/harness-perf/SKILL.md +37 -8
  33. package/dist/agents/skills/claude-code/harness-perf/skill.yaml +3 -0
  34. package/dist/agents/skills/claude-code/harness-perf-tdd/SKILL.md +17 -4
  35. package/dist/agents/skills/claude-code/harness-planning/SKILL.md +59 -5
  36. package/dist/agents/skills/claude-code/harness-planning/skill.yaml +2 -0
  37. package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +16 -0
  38. package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +561 -0
  39. package/dist/agents/skills/claude-code/harness-roadmap/skill.yaml +43 -0
  40. package/dist/agents/skills/claude-code/harness-security-review/SKILL.md +36 -2
  41. package/dist/agents/skills/claude-code/harness-security-review/skill.yaml +8 -6
  42. package/dist/agents/skills/claude-code/harness-soundness-review/SKILL.md +1267 -0
  43. package/dist/agents/skills/claude-code/harness-soundness-review/skill.yaml +48 -0
  44. package/dist/agents/skills/claude-code/harness-test-advisor/SKILL.md +35 -6
  45. package/dist/agents/skills/claude-code/harness-verification/SKILL.md +66 -0
  46. package/dist/agents/skills/claude-code/harness-verification/skill.yaml +1 -0
  47. package/dist/agents/skills/claude-code/harness-verify/SKILL.md +11 -0
  48. package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +15 -1
  49. package/dist/agents/skills/claude-code/validate-context-engineering/SKILL.md +12 -0
  50. package/dist/agents/skills/gemini-cli/add-harness-component/SKILL.md +192 -0
  51. package/dist/agents/skills/gemini-cli/add-harness-component/skill.yaml +32 -0
  52. package/dist/agents/skills/gemini-cli/align-documentation/SKILL.md +213 -0
  53. package/dist/agents/skills/gemini-cli/align-documentation/skill.yaml +31 -0
  54. package/dist/agents/skills/gemini-cli/check-mechanical-constraints/SKILL.md +191 -0
  55. package/dist/agents/skills/gemini-cli/check-mechanical-constraints/skill.yaml +32 -0
  56. package/dist/agents/skills/gemini-cli/cleanup-dead-code/SKILL.md +245 -0
  57. package/dist/agents/skills/gemini-cli/cleanup-dead-code/skill.yaml +33 -0
  58. package/dist/agents/skills/gemini-cli/detect-doc-drift/SKILL.md +179 -0
  59. package/dist/agents/skills/gemini-cli/detect-doc-drift/skill.yaml +30 -0
  60. package/dist/agents/skills/gemini-cli/enforce-architecture/SKILL.md +240 -0
  61. package/dist/agents/skills/gemini-cli/enforce-architecture/skill.yaml +34 -0
  62. package/dist/agents/skills/gemini-cli/harness-accessibility/SKILL.md +7 -0
  63. package/dist/agents/skills/gemini-cli/harness-architecture-advisor/SKILL.md +397 -0
  64. package/dist/agents/skills/gemini-cli/harness-architecture-advisor/skill.yaml +48 -0
  65. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +11 -3
  66. package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +317 -0
  67. package/dist/agents/skills/gemini-cli/harness-brainstorming/skill.yaml +49 -0
  68. package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +681 -0
  69. package/dist/agents/skills/gemini-cli/harness-code-review/skill.yaml +45 -0
  70. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/SKILL.md +226 -0
  71. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/skill.yaml +64 -0
  72. package/dist/agents/skills/gemini-cli/harness-debugging/SKILL.md +366 -0
  73. package/dist/agents/skills/gemini-cli/harness-debugging/skill.yaml +47 -0
  74. package/dist/agents/skills/gemini-cli/harness-dependency-health/SKILL.md +35 -6
  75. package/dist/agents/skills/gemini-cli/harness-diagnostics/SKILL.md +318 -0
  76. package/dist/agents/skills/gemini-cli/harness-diagnostics/skill.yaml +50 -0
  77. package/dist/agents/skills/gemini-cli/harness-docs-pipeline/SKILL.md +460 -0
  78. package/dist/agents/skills/gemini-cli/harness-docs-pipeline/skill.yaml +69 -0
  79. package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +382 -0
  80. package/dist/agents/skills/gemini-cli/harness-execution/skill.yaml +51 -0
  81. package/dist/agents/skills/gemini-cli/harness-git-workflow/SKILL.md +268 -0
  82. package/dist/agents/skills/gemini-cli/harness-git-workflow/skill.yaml +31 -0
  83. package/dist/agents/skills/gemini-cli/harness-hotspot-detector/SKILL.md +32 -6
  84. package/dist/agents/skills/gemini-cli/harness-i18n/SKILL.md +484 -0
  85. package/dist/agents/skills/gemini-cli/harness-i18n/skill.yaml +54 -0
  86. package/dist/agents/skills/gemini-cli/harness-i18n-process/SKILL.md +388 -0
  87. package/dist/agents/skills/gemini-cli/harness-i18n-process/skill.yaml +43 -0
  88. package/dist/agents/skills/gemini-cli/harness-i18n-workflow/SKILL.md +512 -0
  89. package/dist/agents/skills/gemini-cli/harness-i18n-workflow/skill.yaml +53 -0
  90. package/dist/agents/skills/gemini-cli/harness-impact-analysis/SKILL.md +35 -6
  91. package/dist/agents/skills/gemini-cli/harness-integrity/SKILL.md +167 -0
  92. package/dist/agents/skills/gemini-cli/harness-integrity/skill.yaml +47 -0
  93. package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/SKILL.md +46 -5
  94. package/dist/agents/skills/gemini-cli/harness-onboarding/SKILL.md +288 -0
  95. package/dist/agents/skills/gemini-cli/harness-onboarding/skill.yaml +30 -0
  96. package/dist/agents/skills/gemini-cli/harness-parallel-agents/SKILL.md +171 -0
  97. package/dist/agents/skills/gemini-cli/harness-parallel-agents/skill.yaml +33 -0
  98. package/dist/agents/skills/gemini-cli/harness-perf/SKILL.md +37 -8
  99. package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +3 -0
  100. package/dist/agents/skills/gemini-cli/harness-perf-tdd/SKILL.md +17 -4
  101. package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +389 -0
  102. package/dist/agents/skills/gemini-cli/harness-planning/skill.yaml +49 -0
  103. package/dist/agents/skills/gemini-cli/harness-pre-commit-review/SKILL.md +262 -0
  104. package/dist/agents/skills/gemini-cli/harness-pre-commit-review/skill.yaml +33 -0
  105. package/dist/agents/skills/gemini-cli/harness-refactoring/SKILL.md +169 -0
  106. package/dist/agents/skills/gemini-cli/harness-refactoring/skill.yaml +33 -0
  107. package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +16 -0
  108. package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +561 -0
  109. package/dist/agents/skills/gemini-cli/harness-roadmap/skill.yaml +43 -0
  110. package/dist/agents/skills/gemini-cli/harness-security-review/skill.yaml +8 -6
  111. package/dist/agents/skills/gemini-cli/harness-skill-authoring/SKILL.md +292 -0
  112. package/dist/agents/skills/gemini-cli/harness-skill-authoring/skill.yaml +32 -0
  113. package/dist/agents/skills/gemini-cli/harness-soundness-review/SKILL.md +1267 -0
  114. package/dist/agents/skills/gemini-cli/harness-soundness-review/skill.yaml +48 -0
  115. package/dist/agents/skills/gemini-cli/harness-state-management/SKILL.md +309 -0
  116. package/dist/agents/skills/gemini-cli/harness-state-management/skill.yaml +32 -0
  117. package/dist/agents/skills/gemini-cli/harness-tdd/SKILL.md +177 -0
  118. package/dist/agents/skills/gemini-cli/harness-tdd/skill.yaml +48 -0
  119. package/dist/agents/skills/gemini-cli/harness-test-advisor/SKILL.md +35 -6
  120. package/dist/agents/skills/gemini-cli/harness-verification/SKILL.md +328 -0
  121. package/dist/agents/skills/gemini-cli/harness-verification/skill.yaml +42 -0
  122. package/dist/agents/skills/gemini-cli/harness-verify/SKILL.md +159 -0
  123. package/dist/agents/skills/gemini-cli/harness-verify/skill.yaml +40 -0
  124. package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +224 -0
  125. package/dist/agents/skills/gemini-cli/initialize-harness-project/skill.yaml +31 -0
  126. package/dist/agents/skills/gemini-cli/validate-context-engineering/SKILL.md +150 -0
  127. package/dist/agents/skills/gemini-cli/validate-context-engineering/skill.yaml +31 -0
  128. package/dist/agents/skills/shared/i18n-knowledge/accessibility/intersection.yaml +142 -0
  129. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/encoding.yaml +67 -0
  130. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/formatting.yaml +106 -0
  131. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/layout.yaml +80 -0
  132. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/pluralization.yaml +80 -0
  133. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/string-handling.yaml +106 -0
  134. package/dist/agents/skills/shared/i18n-knowledge/frameworks/android-resources.yaml +47 -0
  135. package/dist/agents/skills/shared/i18n-knowledge/frameworks/apple-strings.yaml +47 -0
  136. package/dist/agents/skills/shared/i18n-knowledge/frameworks/backend-patterns.yaml +50 -0
  137. package/dist/agents/skills/shared/i18n-knowledge/frameworks/flutter-intl.yaml +47 -0
  138. package/dist/agents/skills/shared/i18n-knowledge/frameworks/i18next.yaml +47 -0
  139. package/dist/agents/skills/shared/i18n-knowledge/frameworks/react-intl.yaml +47 -0
  140. package/dist/agents/skills/shared/i18n-knowledge/frameworks/vue-i18n.yaml +47 -0
  141. package/dist/agents/skills/shared/i18n-knowledge/industries/ecommerce.yaml +66 -0
  142. package/dist/agents/skills/shared/i18n-knowledge/industries/fintech.yaml +66 -0
  143. package/dist/agents/skills/shared/i18n-knowledge/industries/gaming.yaml +69 -0
  144. package/dist/agents/skills/shared/i18n-knowledge/industries/healthcare.yaml +66 -0
  145. package/dist/agents/skills/shared/i18n-knowledge/industries/legal.yaml +66 -0
  146. package/dist/agents/skills/shared/i18n-knowledge/locales/ar.yaml +41 -0
  147. package/dist/agents/skills/shared/i18n-knowledge/locales/de.yaml +35 -0
  148. package/dist/agents/skills/shared/i18n-knowledge/locales/en.yaml +32 -0
  149. package/dist/agents/skills/shared/i18n-knowledge/locales/es.yaml +35 -0
  150. package/dist/agents/skills/shared/i18n-knowledge/locales/fi.yaml +35 -0
  151. package/dist/agents/skills/shared/i18n-knowledge/locales/fr.yaml +35 -0
  152. package/dist/agents/skills/shared/i18n-knowledge/locales/he.yaml +41 -0
  153. package/dist/agents/skills/shared/i18n-knowledge/locales/hi.yaml +35 -0
  154. package/dist/agents/skills/shared/i18n-knowledge/locales/it.yaml +32 -0
  155. package/dist/agents/skills/shared/i18n-knowledge/locales/ja.yaml +38 -0
  156. package/dist/agents/skills/shared/i18n-knowledge/locales/ko.yaml +38 -0
  157. package/dist/agents/skills/shared/i18n-knowledge/locales/nl.yaml +32 -0
  158. package/dist/agents/skills/shared/i18n-knowledge/locales/pl.yaml +35 -0
  159. package/dist/agents/skills/shared/i18n-knowledge/locales/pt.yaml +32 -0
  160. package/dist/agents/skills/shared/i18n-knowledge/locales/ru.yaml +35 -0
  161. package/dist/agents/skills/shared/i18n-knowledge/locales/sv.yaml +32 -0
  162. package/dist/agents/skills/shared/i18n-knowledge/locales/th.yaml +35 -0
  163. package/dist/agents/skills/shared/i18n-knowledge/locales/tr.yaml +35 -0
  164. package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hans.yaml +38 -0
  165. package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hant.yaml +35 -0
  166. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/i18next-mcp.yaml +56 -0
  167. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lingo-dev.yaml +56 -0
  168. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lokalise.yaml +60 -0
  169. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/tolgee.yaml +60 -0
  170. package/dist/agents/skills/shared/i18n-knowledge/testing/locale-testing.yaml +107 -0
  171. package/dist/agents/skills/shared/i18n-knowledge/testing/pseudo-localization.yaml +86 -0
  172. package/dist/bin/harness.js +64 -4
  173. package/dist/{chunk-GA6GN5J2.js → chunk-E2RTDBMG.js} +2263 -41
  174. package/dist/{chunk-FFIX3QVG.js → chunk-KJANDVVC.js} +141 -49
  175. package/dist/{chunk-4WUGOJQ7.js → chunk-RT2LYQHF.js} +1 -1
  176. package/dist/{dist-C4J67MPP.js → dist-CCM3L3UE.js} +95 -1
  177. package/dist/{dist-N4D4QWFV.js → dist-K6KTTN3I.js} +4 -4
  178. package/dist/index.d.ts +187 -7
  179. package/dist/index.js +7 -3
  180. package/dist/validate-cross-check-ZGKFQY57.js +7 -0
  181. package/package.json +9 -9
  182. package/dist/agents/skills/node_modules/.bin/glob +0 -17
  183. package/dist/agents/skills/node_modules/.bin/vitest +0 -17
  184. package/dist/agents/skills/node_modules/.bin/yaml +0 -17
  185. package/dist/templates/advanced/docs/specs/.gitkeep +0 -0
  186. package/dist/templates/intermediate/docs/specs/.gitkeep +0 -0
  187. package/dist/validate-cross-check-WGXQ7K62.js +0 -7
@@ -0,0 +1,106 @@
1
+ description: "Formatting anti-patterns — common mistakes in number, date, currency, phone, and address formatting across locales"
2
+
3
+ patterns:
4
+ - name: "Date formatting without locale"
5
+ severity: error
6
+ scope: all
7
+ detect:
8
+ method: "Check for toLocaleDateString() without locale argument or manual date string construction"
9
+ context: "new Date().toLocaleDateString() without first arg, or month + '/' + day + '/' + year concatenation"
10
+ reason: "Without explicit locale, the runtime's default locale is used — which may differ from the user's locale on servers or CI."
11
+ instead: "Always pass locale: new Intl.DateTimeFormat(userLocale, options).format(date)"
12
+ strictness:
13
+ permissive: info
14
+ standard: warn
15
+ strict: error
16
+
17
+ - name: "Number formatting with hardcoded separators"
18
+ severity: error
19
+ scope: all
20
+ detect:
21
+ method: "Check for regex or replace operations that insert commas or periods as number separators"
22
+ context: "value.toFixed(2).replace('.', ',') or regex-based thousand separator insertion"
23
+ reason: "Decimal separator is comma in most of Europe (1.234,56), period in US/UK (1,234.56), and momayyez in Arabic."
24
+ instead: "Use Intl.NumberFormat(locale).format(value) for all number display"
25
+ strictness:
26
+ permissive: warn
27
+ standard: error
28
+ strict: error
29
+
30
+ - name: "Currency display with hardcoded symbol"
31
+ severity: error
32
+ scope: all
33
+ detect:
34
+ method: "Check for string concatenation with currency symbols: '$' + amount or amount + ' EUR'"
35
+ context: "Currency symbol prepended or appended to a formatted number"
36
+ reason: "Symbol position varies: $100 (en-US), 100 $ (fr-FR), 100$ (pt-BR). Some currencies use code (CHF) not symbol."
37
+ instead: "Use Intl.NumberFormat(locale, { style: 'currency', currency: code }).format(amount)"
38
+ strictness:
39
+ permissive: warn
40
+ standard: error
41
+ strict: error
42
+
43
+ - name: "Phone number formatting without libphonenumber"
44
+ severity: warning
45
+ scope: all
46
+ detect:
47
+ method: "Check for regex-based phone number formatting or validation"
48
+ context: "Phone regex like /^\\d{10}$/ or manual formatting with dashes and parentheses"
49
+ reason: "Phone number formats vary enormously by country. UK: 020 7946 0958. US: (202) 555-0123. Japan: 03-1234-5678."
50
+ instead: "Use google-libphonenumber for parsing, validation, and formatting; store in E.164 format"
51
+ strictness:
52
+ permissive: info
53
+ standard: warn
54
+ strict: warn
55
+
56
+ - name: "Address formatting with hardcoded field order"
57
+ severity: warning
58
+ scope: all
59
+ detect:
60
+ method: "Check for address string templates that assume a fixed field order"
61
+ context: "Template like `${street}, ${city}, ${state} ${zip}` used for all countries"
62
+ reason: "Japan: postal code first, then prefecture, city, street. Germany: street, then postal code + city (same line). Formats vary worldwide."
63
+ instead: "Use Google's libaddressinput or i18n-postal-address for country-specific address formatting"
64
+ strictness:
65
+ permissive: info
66
+ standard: warn
67
+ strict: warn
68
+
69
+ - name: "Percentage formatting assumptions"
70
+ severity: warning
71
+ scope: all
72
+ detect:
73
+ method: "Check for percentage display constructed by appending '%' to a number"
74
+ context: "value + '%' or `${value}%` without locale-aware formatting"
75
+ reason: "Some locales put a space before % (French: 25 %). Turkish uses %25 (prefix). Arabic may use the Arabic percent sign."
76
+ instead: "Use Intl.NumberFormat(locale, { style: 'percent' }).format(value / 100)"
77
+ strictness:
78
+ permissive: info
79
+ standard: warn
80
+ strict: warn
81
+
82
+ - name: "Hardcoded decimal precision"
83
+ severity: error
84
+ scope: all
85
+ detect:
86
+ method: "Check for .toFixed(2) applied to currency amounts"
87
+ context: "Universal 2-decimal-place formatting for all currencies"
88
+ reason: "JPY and KRW have 0 decimal places. BHD and KWD have 3. Using 2 for all misrepresents amounts."
89
+ instead: "Use Intl.NumberFormat with currency option which auto-selects correct precision per currency code"
90
+ strictness:
91
+ permissive: warn
92
+ standard: error
93
+ strict: error
94
+
95
+ - name: "Time zone display without IANA identifier"
96
+ severity: warning
97
+ scope: all
98
+ detect:
99
+ method: "Check for timezone abbreviations (EST, PST, CET) in user-facing display"
100
+ context: "Displaying 'EST' or 'PST' without the full IANA timezone identifier"
101
+ reason: "Timezone abbreviations are ambiguous (CST = Central Standard Time or China Standard Time) and not universally understood."
102
+ instead: "Use IANA identifiers (America/New_York) for storage; display user-friendly names via Intl.DateTimeFormat with timeZoneName option"
103
+ strictness:
104
+ permissive: info
105
+ standard: warn
106
+ strict: warn
@@ -0,0 +1,80 @@
1
+ description: "Layout anti-patterns — common mistakes in spatial design, text containers, and directional assumptions that break in localized contexts"
2
+
3
+ patterns:
4
+ - name: "Fixed-width containers for text"
5
+ severity: error
6
+ scope: all
7
+ detect:
8
+ method: "Check for fixed pixel widths on containers that hold translated text"
9
+ context: "Buttons, labels, or cards with hardcoded width in px that hold user-facing text"
10
+ reason: "German expands 30-35% over English. Finnish expands up to 40%. Fixed-width containers cause text overflow or truncation."
11
+ instead: "Use min-width/max-width with flexible layouts; test with the longest target language (typically German or Finnish)"
12
+ strictness:
13
+ permissive: info
14
+ standard: warn
15
+ strict: error
16
+
17
+ - name: "Hardcoded CSS left/right instead of logical properties"
18
+ severity: warning
19
+ scope: web
20
+ detect:
21
+ method: "Check for CSS properties using physical directions: margin-left, padding-right, text-align: left, float: left"
22
+ context: "Layout CSS that uses physical direction properties instead of logical equivalents"
23
+ reason: "Physical left/right breaks in RTL layouts. margin-left becomes the wrong side for Arabic and Hebrew users."
24
+ instead: "Use CSS logical properties: margin-inline-start, padding-inline-end, text-align: start, float: inline-start"
25
+ strictness:
26
+ permissive: info
27
+ standard: warn
28
+ strict: warn
29
+
30
+ - name: "Icon placement assumptions"
31
+ severity: warning
32
+ scope: all
33
+ detect:
34
+ method: "Check for icons hardcoded to left or right side of text"
35
+ context: "Arrow icons, action icons, or navigation indicators with fixed directional placement"
36
+ reason: "Left-side icons in LTR become wrong-side icons in RTL. But some icons should NOT mirror (checkmarks, media play buttons)."
37
+ instead: "Use logical placement (inline-start/end); create an icon exception list for icons that should not mirror in RTL"
38
+ strictness:
39
+ permissive: info
40
+ standard: warn
41
+ strict: warn
42
+
43
+ - name: "Text truncation without dir attribute"
44
+ severity: warning
45
+ scope: web
46
+ detect:
47
+ method: "Check for text-overflow: ellipsis without corresponding dir attribute on the container"
48
+ context: "Truncated text elements that may contain RTL content"
49
+ reason: "Ellipsis appears at the wrong end for RTL text without dir attribute. Bidi truncation shows '...مرحبا' instead of 'مرحبا...'"
50
+ instead: "Set dir attribute on text containers; use CSS direction property in conjunction with text-overflow"
51
+ strictness:
52
+ permissive: info
53
+ standard: warn
54
+ strict: warn
55
+
56
+ - name: "Fixed height on text containers"
57
+ severity: warning
58
+ scope: all
59
+ detect:
60
+ method: "Check for fixed pixel heights on containers that hold multi-line translated text"
61
+ context: "Cards, tooltips, or modals with hardcoded height that hold translatable content"
62
+ reason: "Translated text may wrap to more lines due to expansion. Thai and Devanagari need more vertical space for diacritics."
63
+ instead: "Use min-height instead of height; increase line-height for scripts with stacking diacritics (Thai: 1.8, Devanagari: 1.6)"
64
+ strictness:
65
+ permissive: info
66
+ standard: warn
67
+ strict: warn
68
+
69
+ - name: "Images or graphics containing embedded text"
70
+ severity: error
71
+ scope: all
72
+ detect:
73
+ method: "Check for images, SVGs, or canvas elements with text baked into the visual"
74
+ context: "Hero images, infographics, or icons with embedded text labels"
75
+ reason: "Text in images cannot be translated, searched, or read by screen readers. Each locale requires a new image asset."
76
+ instead: "Overlay text on images using CSS positioning; use SVG with <text> elements that can reference translation keys"
77
+ strictness:
78
+ permissive: info
79
+ standard: warn
80
+ strict: error
@@ -0,0 +1,80 @@
1
+ description: "Pluralization anti-patterns — common mistakes in handling plural forms across languages with varying CLDR plural categories"
2
+
3
+ patterns:
4
+ - name: "Binary plural logic"
5
+ severity: error
6
+ scope: all
7
+ detect:
8
+ method: "Check for ternary or if/else that only handles singular and plural (two forms)"
9
+ context: "count === 1 ? singular : plural or count > 1 ? plural : singular"
10
+ reason: "Many languages need more than two forms. Arabic has 6 (zero, one, two, few, many, other). Polish has 4. Russian has 4. Binary logic covers only English-like languages."
11
+ instead: "Use ICU MessageFormat plural syntax with all needed CLDR categories: {count, plural, zero {...} one {...} two {...} few {...} many {...} other {...}}"
12
+ strictness:
13
+ permissive: warn
14
+ standard: error
15
+ strict: error
16
+
17
+ - name: "Hardcoded English plural rules applied to all locales"
18
+ severity: error
19
+ scope: all
20
+ detect:
21
+ method: "Check for plural functions that add 's' suffix or check count === 1"
22
+ context: "Functions like pluralize(word, count) that append 's' or select between two English forms"
23
+ reason: "English plural rule (add 's') is specific to English. Most languages have completely different plural morphology."
24
+ instead: "Delegate pluralization entirely to the i18n framework which implements CLDR plural rules per locale"
25
+ strictness:
26
+ permissive: warn
27
+ standard: error
28
+ strict: error
29
+
30
+ - name: "Missing CLDR plural categories for target locales"
31
+ severity: error
32
+ scope: all
33
+ detect:
34
+ method: "Check translation files for missing plural category keys compared to what CLDR requires for each locale"
35
+ context: "Arabic translation file with only 'one' and 'other' forms instead of all 6 required forms"
36
+ reason: "Missing plural forms cause fallback to 'other' which may be grammatically incorrect for specific counts."
37
+ instead: "Audit translation files against CLDR plural rules for each target locale; ensure all required categories are present"
38
+ strictness:
39
+ permissive: info
40
+ standard: warn
41
+ strict: error
42
+
43
+ - name: "Ordinal pluralization not handled"
44
+ severity: warning
45
+ scope: all
46
+ detect:
47
+ method: "Check for ordinal display (1st, 2nd, 3rd) constructed manually or with English-only rules"
48
+ context: "Appending 'st', 'nd', 'rd', 'th' suffixes based on English ordinal rules"
49
+ reason: "Ordinal rules vary by locale. English: 1st, 2nd, 3rd. French: 1er, 2e. German: 1., 2. Some languages have no written ordinal form."
50
+ instead: "Use Intl.PluralRules(locale, { type: 'ordinal' }) to select the correct ordinal form per locale"
51
+ strictness:
52
+ permissive: info
53
+ standard: warn
54
+ strict: warn
55
+
56
+ - name: "Plural forms embedded in UI code instead of message format"
57
+ severity: warning
58
+ scope: all
59
+ detect:
60
+ method: "Check for conditional rendering of plural text in component code rather than translation files"
61
+ context: "JSX like {count === 1 ? <span>1 item</span> : <span>{count} items</span>}"
62
+ reason: "Plural logic in code bypasses the translation pipeline. Translators cannot adapt plural forms for their locale."
63
+ instead: "Move plural selection to translation files using ICU or framework plural syntax; render with a single translation key"
64
+ strictness:
65
+ permissive: info
66
+ standard: warn
67
+ strict: warn
68
+
69
+ - name: "Count-based display without using plural-aware formatter"
70
+ severity: warning
71
+ scope: all
72
+ detect:
73
+ method: "Check for number + noun patterns constructed without plural formatter"
74
+ context: "Displaying '5 file(s)' or using parenthetical plural as a workaround"
75
+ reason: "The '(s)' workaround is not grammatical in any language. It looks unprofessional and confuses screen readers."
76
+ instead: "Use proper plural formatting: t('files', { count: 5 }) with locale-specific plural forms in translation files"
77
+ strictness:
78
+ permissive: info
79
+ standard: warn
80
+ strict: warn
@@ -0,0 +1,106 @@
1
+ description: "String handling anti-patterns — common mistakes in text manipulation, concatenation, and string operations that break in localized contexts"
2
+
3
+ patterns:
4
+ - name: "String concatenation for sentences"
5
+ severity: error
6
+ scope: all
7
+ detect:
8
+ method: "Check for string concatenation of user-facing text segments"
9
+ context: "Expressions like 'Hello, ' + name + '!' or `Welcome to ${place}`"
10
+ reason: "Word order varies by locale. 'Hello, {name}!' in English becomes '{name}さん、こんにちは!' in Japanese — the name comes first."
11
+ instead: "Use ICU MessageFormat or framework translation function with named placeholders: t('greeting', { name })"
12
+ strictness:
13
+ permissive: info
14
+ standard: warn
15
+ strict: error
16
+
17
+ - name: "Hardcoded user-facing strings"
18
+ severity: error
19
+ scope: all
20
+ detect:
21
+ method: "Check for string literals in JSX, templates, or UI rendering code"
22
+ context: "Text nodes in JSX, template literals in HTML attributes, string args to UI components"
23
+ reason: "Untranslated strings are invisible to the localization pipeline. They remain in the source language for all users."
24
+ instead: "Wrap all user-facing strings in the framework's translation function (t(), $t(), FormattedMessage, etc.)"
25
+ strictness:
26
+ permissive: info
27
+ standard: warn
28
+ strict: error
29
+
30
+ - name: "Substring or split on translated strings"
31
+ severity: warning
32
+ scope: all
33
+ detect:
34
+ method: "Check for .substring(), .split(), .slice() applied to translated text"
35
+ context: "Operations that assume word boundaries or character positions in translated strings"
36
+ reason: "Word boundaries differ by locale. CJK has no spaces. Thai has no word breaks. Splitting on space fails."
37
+ instead: "Use Intl.Segmenter for locale-aware text segmentation; redesign to avoid splitting translated text"
38
+ strictness:
39
+ permissive: info
40
+ standard: warn
41
+ strict: warn
42
+
43
+ - name: "Hardcoded plural logic"
44
+ severity: error
45
+ scope: all
46
+ detect:
47
+ method: "Check for ternary or if/else choosing singular vs plural form"
48
+ context: "count === 1 ? 'item' : 'items' or similar binary plural selection"
49
+ reason: "Arabic has 6 plural forms. Polish has 4. Welsh has 6. Binary singular/plural only works for a few languages."
50
+ instead: "Use CLDR plural rules via ICU MessageFormat: {count, plural, one {# item} other {# items}}"
51
+ strictness:
52
+ permissive: warn
53
+ standard: error
54
+ strict: error
55
+
56
+ - name: "String templates with positional assumptions"
57
+ severity: warning
58
+ scope: all
59
+ detect:
60
+ method: "Check for template literals or format strings that assume a fixed order of interpolated values"
61
+ context: "Patterns like `${greeting} ${name}` or String.format('%s %s', greeting, name)"
62
+ reason: "Interpolation order may need to change per locale. Japanese may need name before greeting."
63
+ instead: "Use named placeholders ({greeting} {name}) so translators can reorder: '{name}さん、{greeting}'"
64
+ strictness:
65
+ permissive: info
66
+ standard: warn
67
+ strict: warn
68
+
69
+ - name: "UI text in code comments used as display strings"
70
+ severity: warning
71
+ scope: all
72
+ detect:
73
+ method: "Check for display text stored in constants or enums without translation function wrapping"
74
+ context: "const LABEL = 'Submit' or enum Status { Active = 'Active' } used directly in UI"
75
+ reason: "Constants and enum values are not extracted by localization tools. They bypass the translation pipeline."
76
+ instead: "Map enum values to translation keys: const LABELS = { active: t('status.active') }"
77
+ strictness:
78
+ permissive: info
79
+ standard: warn
80
+ strict: warn
81
+
82
+ - name: "String length validation on translated input"
83
+ severity: warning
84
+ scope: all
85
+ detect:
86
+ method: "Check for maxLength validation on text that will be translated or on user input from localized forms"
87
+ context: "Input validation like value.length <= 50 applied to fields that accept multilingual input"
88
+ reason: "A 50-character limit may be too short for German translations (30-35% expansion) or too long for CJK (visual width differs)."
89
+ instead: "Use visual width constraints (CSS max-width) instead of character count; adjust limits per locale if needed"
90
+ strictness:
91
+ permissive: info
92
+ standard: warn
93
+ strict: warn
94
+
95
+ - name: "Case transformation without locale"
96
+ severity: error
97
+ scope: all
98
+ detect:
99
+ method: "Check for .toUpperCase() and .toLowerCase() without locale argument"
100
+ context: "String case operations that do not use toLocaleUpperCase() or toLocaleLowerCase()"
101
+ reason: "Turkish dotted-i bug: 'istanbul'.toUpperCase() produces 'ISTANBUL' (wrong) instead of 'ISTANBUL'. German eszett: 'strasse'.toUpperCase() should consider locale."
102
+ instead: "Always use toLocaleUpperCase(locale) and toLocaleLowerCase(locale) for user-facing text"
103
+ strictness:
104
+ permissive: info
105
+ standard: warn
106
+ strict: error
@@ -0,0 +1,47 @@
1
+ name: "Android Resources"
2
+ description: "Android platform localization using XML string resources and the Android resource system"
3
+ platforms: ["mobile"]
4
+ message_format: "custom"
5
+
6
+ detection:
7
+ package_json_keys:
8
+ dependencies: []
9
+ devDependencies: []
10
+ file_patterns: ["**/res/values*/strings.xml", "**/*.kt", "**/*.java"]
11
+ config_files: ["build.gradle", "build.gradle.kts", "AndroidManifest.xml"]
12
+
13
+ conventions:
14
+ key_format: "snake_case"
15
+ file_format: "xml"
16
+ file_structure: "res/values-{locale}/strings.xml"
17
+ plural_syntax: "<plurals name='items'><item quantity='one'>%d item</item><item quantity='other'>%d items</item></plurals>"
18
+ interpolation_syntax: "%s (positional: %1$s, %2$s)"
19
+
20
+ recommended_tooling:
21
+ extraction: ["Android Studio translation editor", "Lint checks"]
22
+ linting: ["Android Lint (MissingTranslation, HardcodedText)"]
23
+ pseudo_locale: ["Android built-in pseudolocales: en-XA (accented), ar-XB (bidi)"]
24
+
25
+ anti_patterns:
26
+ - pattern: "String concatenation instead of getString() with format args"
27
+ severity: error
28
+ instead: "Use getString(R.string.greeting, userName) with %1$s placeholders in strings.xml"
29
+ - pattern: "Hardcoded strings in layout XML"
30
+ severity: error
31
+ instead: "Use @string/key references in all android:text and android:hint attributes; Android Lint flags these"
32
+ - pattern: "Missing quantity entries in <plurals>"
33
+ severity: error
34
+ instead: "Include all CLDR quantities for target locales (zero, one, two, few, many, other as applicable)"
35
+ - pattern: "Using string-array for translatable content without context"
36
+ severity: warning
37
+ instead: "Add translatorNote attributes or XML comments for string arrays to provide context for translators"
38
+ - pattern: "Not using Android pseudolocales for testing"
39
+ severity: warning
40
+ instead: "Enable en-XA (accented English) and ar-XB (bidi) pseudolocales in developer settings for testing"
41
+
42
+ migration_notes:
43
+ from:
44
+ - framework: "legacy Java ResourceBundle"
45
+ guidance: "Move .properties files to Android XML resources; convert MessageFormat patterns to Android format strings; update getString() calls"
46
+ - framework: "custom key-value solution"
47
+ guidance: "Map keys to Android resource naming conventions (snake_case); create strings.xml per locale in res/values-{locale}/ directories"
@@ -0,0 +1,47 @@
1
+ name: "Apple Strings"
2
+ description: "Apple platform localization using .strings, .stringsdict, and .xcstrings (String Catalogs) files"
3
+ platforms: ["mobile"]
4
+ message_format: "custom"
5
+
6
+ detection:
7
+ package_json_keys:
8
+ dependencies: []
9
+ devDependencies: []
10
+ file_patterns: ["**/*.strings", "**/*.stringsdict", "**/*.xcstrings", "**/*.lproj/**"]
11
+ config_files: ["*.xcodeproj/project.pbxproj", "*.xcworkspace"]
12
+
13
+ conventions:
14
+ key_format: "dot-notation"
15
+ file_format: "strings"
16
+ file_structure: "{locale}.lproj/Localizable.strings"
17
+ plural_syntax: ".stringsdict plist format with NSStringLocalizedFormatKey"
18
+ interpolation_syntax: "%@ (positional: %1$@, %2$@)"
19
+
20
+ recommended_tooling:
21
+ extraction: ["genstrings", "Xcode String Catalog auto-extraction"]
22
+ linting: ["SwiftLint custom rules", "Xcode build warnings"]
23
+ pseudo_locale: ["xcstrings pseudo-locale generation"]
24
+
25
+ anti_patterns:
26
+ - pattern: "Missing .stringsdict for plurals"
27
+ severity: error
28
+ instead: "Create .stringsdict files for all pluralized strings; NSLocalizedString alone cannot handle plural forms"
29
+ - pattern: "Concatenating localized strings"
30
+ severity: error
31
+ instead: "Use String(format:) with positional specifiers: String(format: NSLocalizedString('greeting_%@_%@'), firstName, lastName)"
32
+ - pattern: "Not using String Catalogs (Xcode 15+)"
33
+ severity: info
34
+ instead: "Migrate from .strings/.stringsdict to .xcstrings (String Catalogs) for unified translation management"
35
+ - pattern: "Hardcoded strings in storyboards/XIBs without localization"
36
+ severity: warning
37
+ instead: "Use Base Internationalization with .strings files for Interface Builder, or switch to programmatic UI with NSLocalizedString"
38
+ - pattern: "Not testing with pseudolanguage locale on device"
39
+ severity: warning
40
+ instead: "Enable Double-Length Pseudolanguage in Xcode scheme settings to test text expansion"
41
+
42
+ migration_notes:
43
+ from:
44
+ - framework: "legacy .strings"
45
+ guidance: "Open .strings files in Xcode 15+ and migrate to String Catalogs (.xcstrings); Xcode provides automatic migration; review pluralization rules post-migration"
46
+ - framework: "third-party (Lokalise SDK, Crowdin SDK)"
47
+ guidance: "Replace OTA SDK with build-time .xcstrings integration; use export/import workflows instead of runtime translation fetching"
@@ -0,0 +1,50 @@
1
+ name: "Backend Patterns"
2
+ description: "Cross-platform backend i18n patterns for Node.js, Python, Go, and Java server-side localization"
3
+ platforms: ["backend"]
4
+ message_format: "varies"
5
+
6
+ detection:
7
+ package_json_keys:
8
+ dependencies: ["i18next", "i18n-node", "messageformat", "globalize"]
9
+ devDependencies: []
10
+ file_patterns: ["**/*.py", "**/*.go", "**/*.java", "**/*.ts", "**/*.js", "**/locales/**", "**/translations/**"]
11
+ config_files: ["babel.cfg", "locale.go", "messages.properties", "i18n.config.*"]
12
+
13
+ conventions:
14
+ key_format: "dot-notation"
15
+ file_format: "json"
16
+ file_structure: "locales/{locale}/{namespace}.json"
17
+ plural_syntax: "Varies by runtime: ICU (Node/Java), gettext (Python), go-i18n (Go)"
18
+ interpolation_syntax: "Varies: {variable} (ICU), %(variable)s (Python gettext), {{.Variable}} (Go)"
19
+
20
+ recommended_tooling:
21
+ extraction: ["i18next-parser (Node)", "pybabel extract (Python)", "go-i18n extract (Go)", "ResourceBundle (Java)"]
22
+ linting: ["custom CI checks for missing translations"]
23
+ pseudo_locale: ["pseudo-localization npm package (Node)", "custom generators per platform"]
24
+
25
+ anti_patterns:
26
+ - pattern: "Hardcoded error messages in API responses"
27
+ severity: error
28
+ instead: "Return error codes with locale-neutral keys; resolve to localized messages on the client or in a localization middleware"
29
+ - pattern: "Locale detection only from Accept-Language header"
30
+ severity: warning
31
+ instead: "Support explicit locale preference (user settings), URL path/query, cookie, then Accept-Language as fallback chain"
32
+ - pattern: "Storing translated content in code"
33
+ severity: warning
34
+ instead: "Externalize translations to resource files (JSON, PO, properties); load at runtime per locale"
35
+ - pattern: "Email templates with hardcoded language"
36
+ severity: error
37
+ instead: "Use locale-aware email template engines; store templates per locale; resolve from user's language preference"
38
+ - pattern: "Logging in the user's locale instead of a fixed locale"
39
+ severity: warning
40
+ instead: "Always log in English (or a fixed locale) for consistent log analysis; localize only user-facing output"
41
+ - pattern: "Date/time in API responses without timezone"
42
+ severity: error
43
+ instead: "Always return ISO 8601 with timezone (UTC preferred) in API responses; let clients format for display locale"
44
+
45
+ migration_notes:
46
+ from:
47
+ - framework: "hardcoded strings"
48
+ guidance: "Extract all user-facing strings to resource files; implement a translation function (t/gettext); add locale resolution middleware"
49
+ - framework: "gettext to i18next"
50
+ guidance: "Convert PO/MO files to JSON format; map gettext plurals to i18next suffix convention; update translation function calls"
@@ -0,0 +1,47 @@
1
+ name: "Flutter Intl"
2
+ description: "Dart/Flutter internationalization using the intl package and ARB (Application Resource Bundle) files"
3
+ platforms: ["mobile"]
4
+ message_format: "icu"
5
+
6
+ detection:
7
+ package_json_keys:
8
+ dependencies: ["flutter_localizations", "intl"]
9
+ devDependencies: ["intl_utils", "flutter_gen"]
10
+ file_patterns: ["lib/**/*.dart", "lib/l10n/**/*.arb"]
11
+ config_files: ["l10n.yaml", "pubspec.yaml"]
12
+
13
+ conventions:
14
+ key_format: "camelCase"
15
+ file_format: "arb"
16
+ file_structure: "lib/l10n/app_{locale}.arb"
17
+ plural_syntax: "ICU {count, plural, one {# item} other {# items}}"
18
+ interpolation_syntax: "{variable}"
19
+
20
+ recommended_tooling:
21
+ extraction: ["flutter gen-l10n", "intl_utils"]
22
+ linting: ["dart analyze"]
23
+ pseudo_locale: ["custom ARB generator"]
24
+
25
+ anti_patterns:
26
+ - pattern: "Hardcoded strings in Text() widgets"
27
+ severity: error
28
+ instead: "Use AppLocalizations.of(context)!.messageKey for all user-facing strings"
29
+ - pattern: "Not running flutter gen-l10n after adding new messages"
30
+ severity: warning
31
+ instead: "Run flutter gen-l10n to regenerate the AppLocalizations class after modifying ARB files"
32
+ - pattern: "Using string interpolation for plurals"
33
+ severity: error
34
+ instead: "Use ICU plural syntax in ARB files: {count, plural, one {# item} other {# items}}"
35
+ - pattern: "Missing @metadata descriptions in ARB files"
36
+ severity: info
37
+ instead: "Add @messageKey descriptions for translator context: '@greeting': {'description': 'Welcome message on home screen'}"
38
+ - pattern: "Not testing with different locale settings on device"
39
+ severity: warning
40
+ instead: "Use Flutter integration tests with different locale configurations; test RTL with Arabic locale"
41
+
42
+ migration_notes:
43
+ from:
44
+ - framework: "easy_localization"
45
+ guidance: "Convert JSON translation files to ARB format; replace tr() calls with AppLocalizations.of(context); update locale loading configuration in MaterialApp"
46
+ - framework: "get (GetX i18n)"
47
+ guidance: "Move from Map-based translations to ARB files; replace 'key'.tr with AppLocalizations; configure locale resolution in MaterialApp.localizationsDelegates"
@@ -0,0 +1,47 @@
1
+ name: "i18next"
2
+ description: "Full-featured i18n framework with plugins for React, Vue, Node, and many other platforms"
3
+ platforms: ["web", "mobile", "backend"]
4
+ message_format: "i18next"
5
+
6
+ detection:
7
+ package_json_keys:
8
+ dependencies: ["i18next", "react-i18next", "next-i18next", "i18next-http-backend", "i18next-browser-languagedetector"]
9
+ devDependencies: ["i18next-parser", "i18next-scanner"]
10
+ file_patterns: ["src/**/*.{ts,tsx,js,jsx}", "public/locales/**/*.json"]
11
+ config_files: ["i18next.config.js", "i18next.config.ts", "next-i18next.config.js"]
12
+
13
+ conventions:
14
+ key_format: "nested"
15
+ file_format: "json"
16
+ file_structure: "public/locales/{locale}/{namespace}.json"
17
+ plural_syntax: "key_one: '# item', key_other: '# items' (suffix-based)"
18
+ interpolation_syntax: "{{variable}}"
19
+
20
+ recommended_tooling:
21
+ extraction: ["i18next-parser", "i18next-scanner"]
22
+ linting: ["eslint-plugin-i18next"]
23
+ pseudo_locale: ["i18next-pseudo"]
24
+
25
+ anti_patterns:
26
+ - pattern: "Not using the count option for pluralization"
27
+ severity: error
28
+ instead: "Pass { count: n } to t() function: t('items', { count: itemCount }) — i18next auto-selects the plural form"
29
+ - pattern: "Nesting translations with $t() inside translations"
30
+ severity: warning
31
+ instead: "Use flat interpolation or context-based keys instead of nested $t() references which are hard to extract"
32
+ - pattern: "Loading all namespaces upfront"
33
+ severity: warning
34
+ instead: "Use lazy loading with i18next-http-backend to load namespaces on demand for better performance"
35
+ - pattern: "Hardcoding the fallback language in multiple places"
36
+ severity: warning
37
+ instead: "Configure fallbackLng once in i18next.init(); use namespace-level fallbacks for granular control"
38
+ - pattern: "Using the t() function outside React components without proper initialization"
39
+ severity: error
40
+ instead: "Use i18next.t() directly for non-React code, or pass the t function from initialized context"
41
+
42
+ migration_notes:
43
+ from:
44
+ - framework: "react-intl"
45
+ guidance: "Convert ICU {variable} to {{variable}}; convert ICU plural syntax to suffix-based keys (_one, _other); replace FormattedMessage with useTranslation() hook"
46
+ - framework: "custom-solution"
47
+ guidance: "Map existing key-value pairs to i18next namespace structure; configure fallback chains; add language detection plugin"