@harness-engineering/cli 1.7.0 → 1.8.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.
Files changed (130) 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 +9 -1
  11. package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +76 -4
  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 +57 -3
  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 +562 -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/harness-accessibility/SKILL.md +7 -0
  51. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +9 -1
  52. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/SKILL.md +226 -0
  53. package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/skill.yaml +64 -0
  54. package/dist/agents/skills/gemini-cli/harness-dependency-health/SKILL.md +35 -6
  55. package/dist/agents/skills/gemini-cli/harness-docs-pipeline/SKILL.md +460 -0
  56. package/dist/agents/skills/gemini-cli/harness-docs-pipeline/skill.yaml +69 -0
  57. package/dist/agents/skills/gemini-cli/harness-hotspot-detector/SKILL.md +32 -6
  58. package/dist/agents/skills/gemini-cli/harness-i18n/SKILL.md +484 -0
  59. package/dist/agents/skills/gemini-cli/harness-i18n/skill.yaml +54 -0
  60. package/dist/agents/skills/gemini-cli/harness-i18n-process/SKILL.md +388 -0
  61. package/dist/agents/skills/gemini-cli/harness-i18n-process/skill.yaml +43 -0
  62. package/dist/agents/skills/gemini-cli/harness-i18n-workflow/SKILL.md +512 -0
  63. package/dist/agents/skills/gemini-cli/harness-i18n-workflow/skill.yaml +53 -0
  64. package/dist/agents/skills/gemini-cli/harness-impact-analysis/SKILL.md +35 -6
  65. package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/SKILL.md +46 -5
  66. package/dist/agents/skills/gemini-cli/harness-perf/SKILL.md +37 -8
  67. package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +3 -0
  68. package/dist/agents/skills/gemini-cli/harness-perf-tdd/SKILL.md +17 -4
  69. package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +16 -0
  70. package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +562 -0
  71. package/dist/agents/skills/gemini-cli/harness-roadmap/skill.yaml +43 -0
  72. package/dist/agents/skills/gemini-cli/harness-security-review/skill.yaml +8 -6
  73. package/dist/agents/skills/gemini-cli/harness-soundness-review/SKILL.md +1267 -0
  74. package/dist/agents/skills/gemini-cli/harness-soundness-review/skill.yaml +48 -0
  75. package/dist/agents/skills/gemini-cli/harness-test-advisor/SKILL.md +35 -6
  76. package/dist/agents/skills/shared/i18n-knowledge/accessibility/intersection.yaml +142 -0
  77. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/encoding.yaml +67 -0
  78. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/formatting.yaml +106 -0
  79. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/layout.yaml +80 -0
  80. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/pluralization.yaml +80 -0
  81. package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/string-handling.yaml +106 -0
  82. package/dist/agents/skills/shared/i18n-knowledge/frameworks/android-resources.yaml +47 -0
  83. package/dist/agents/skills/shared/i18n-knowledge/frameworks/apple-strings.yaml +47 -0
  84. package/dist/agents/skills/shared/i18n-knowledge/frameworks/backend-patterns.yaml +50 -0
  85. package/dist/agents/skills/shared/i18n-knowledge/frameworks/flutter-intl.yaml +47 -0
  86. package/dist/agents/skills/shared/i18n-knowledge/frameworks/i18next.yaml +47 -0
  87. package/dist/agents/skills/shared/i18n-knowledge/frameworks/react-intl.yaml +47 -0
  88. package/dist/agents/skills/shared/i18n-knowledge/frameworks/vue-i18n.yaml +47 -0
  89. package/dist/agents/skills/shared/i18n-knowledge/industries/ecommerce.yaml +66 -0
  90. package/dist/agents/skills/shared/i18n-knowledge/industries/fintech.yaml +66 -0
  91. package/dist/agents/skills/shared/i18n-knowledge/industries/gaming.yaml +69 -0
  92. package/dist/agents/skills/shared/i18n-knowledge/industries/healthcare.yaml +66 -0
  93. package/dist/agents/skills/shared/i18n-knowledge/industries/legal.yaml +66 -0
  94. package/dist/agents/skills/shared/i18n-knowledge/locales/ar.yaml +41 -0
  95. package/dist/agents/skills/shared/i18n-knowledge/locales/de.yaml +35 -0
  96. package/dist/agents/skills/shared/i18n-knowledge/locales/en.yaml +32 -0
  97. package/dist/agents/skills/shared/i18n-knowledge/locales/es.yaml +35 -0
  98. package/dist/agents/skills/shared/i18n-knowledge/locales/fi.yaml +35 -0
  99. package/dist/agents/skills/shared/i18n-knowledge/locales/fr.yaml +35 -0
  100. package/dist/agents/skills/shared/i18n-knowledge/locales/he.yaml +41 -0
  101. package/dist/agents/skills/shared/i18n-knowledge/locales/hi.yaml +35 -0
  102. package/dist/agents/skills/shared/i18n-knowledge/locales/it.yaml +32 -0
  103. package/dist/agents/skills/shared/i18n-knowledge/locales/ja.yaml +38 -0
  104. package/dist/agents/skills/shared/i18n-knowledge/locales/ko.yaml +38 -0
  105. package/dist/agents/skills/shared/i18n-knowledge/locales/nl.yaml +32 -0
  106. package/dist/agents/skills/shared/i18n-knowledge/locales/pl.yaml +35 -0
  107. package/dist/agents/skills/shared/i18n-knowledge/locales/pt.yaml +32 -0
  108. package/dist/agents/skills/shared/i18n-knowledge/locales/ru.yaml +35 -0
  109. package/dist/agents/skills/shared/i18n-knowledge/locales/sv.yaml +32 -0
  110. package/dist/agents/skills/shared/i18n-knowledge/locales/th.yaml +35 -0
  111. package/dist/agents/skills/shared/i18n-knowledge/locales/tr.yaml +35 -0
  112. package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hans.yaml +38 -0
  113. package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hant.yaml +35 -0
  114. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/i18next-mcp.yaml +56 -0
  115. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lingo-dev.yaml +56 -0
  116. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lokalise.yaml +60 -0
  117. package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/tolgee.yaml +60 -0
  118. package/dist/agents/skills/shared/i18n-knowledge/testing/locale-testing.yaml +107 -0
  119. package/dist/agents/skills/shared/i18n-knowledge/testing/pseudo-localization.yaml +86 -0
  120. package/dist/bin/harness.js +64 -4
  121. package/dist/{chunk-4WUGOJQ7.js → chunk-3JWCBVUZ.js} +1 -1
  122. package/dist/{chunk-FFIX3QVG.js → chunk-LNI4T7R6.js} +131 -41
  123. package/dist/{chunk-GA6GN5J2.js → chunk-SJECMKSS.js} +2244 -34
  124. package/dist/{dist-N4D4QWFV.js → dist-BDO5GFEM.js} +1 -1
  125. package/dist/{dist-C4J67MPP.js → dist-NT3GXHQZ.js} +95 -1
  126. package/dist/index.d.ts +187 -7
  127. package/dist/index.js +7 -3
  128. package/dist/validate-cross-check-2OPGCGGU.js +7 -0
  129. package/package.json +7 -7
  130. package/dist/validate-cross-check-WGXQ7K62.js +0 -7
@@ -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"
@@ -0,0 +1,47 @@
1
+ name: "React Intl (FormatJS)"
2
+ description: "ICU MessageFormat-based i18n library for React, part of the FormatJS ecosystem"
3
+ platforms: ["web"]
4
+ message_format: "icu"
5
+
6
+ detection:
7
+ package_json_keys:
8
+ dependencies: ["react-intl", "@formatjs/intl", "@formatjs/intl-messageformat"]
9
+ devDependencies: ["@formatjs/cli", "eslint-plugin-formatjs", "@formatjs/ts-transformer"]
10
+ file_patterns: ["src/**/*.{ts,tsx,js,jsx}"]
11
+ config_files: [".formatjsrc", ".formatjsrc.json"]
12
+
13
+ conventions:
14
+ key_format: "dot-notation"
15
+ file_format: "json"
16
+ file_structure: "lang/{locale}.json"
17
+ plural_syntax: "ICU {count, plural, one {# item} other {# items}}"
18
+ interpolation_syntax: "{variable}"
19
+
20
+ recommended_tooling:
21
+ extraction: ["@formatjs/cli extract"]
22
+ linting: ["eslint-plugin-formatjs"]
23
+ pseudo_locale: ["@formatjs/cli compile --pseudo-locale"]
24
+
25
+ anti_patterns:
26
+ - pattern: "String concatenation inside FormattedMessage"
27
+ severity: error
28
+ instead: "Use ICU MessageFormat with placeholders: <FormattedMessage id='greeting' values={{name}} />"
29
+ - pattern: "Using defaultMessage as the translation key"
30
+ severity: warning
31
+ instead: "Use explicit message IDs (dot-notation) for stable keys; defaultMessage is a fallback, not an ID"
32
+ - pattern: "Inline messages without extraction"
33
+ severity: warning
34
+ instead: "Run @formatjs/cli extract to generate message catalogs; do not manually maintain translation files"
35
+ - pattern: "Using dangerouslySetInnerHTML with translated strings"
36
+ severity: error
37
+ instead: "Use FormattedMessage rich text support: <FormattedMessage values={{b: chunks => <b>{chunks}</b>}} />"
38
+ - pattern: "Not wrapping date/number formatting with FormatJS APIs"
39
+ severity: warning
40
+ instead: "Use intl.formatDate(), intl.formatNumber(), and intl.formatRelativeTime() for locale-aware formatting"
41
+
42
+ migration_notes:
43
+ from:
44
+ - framework: "i18next"
45
+ guidance: "Convert {{variable}} interpolation to {variable}; convert i18next plural suffixes (_one, _other) to ICU plural syntax; update extraction pipeline from i18next-parser to @formatjs/cli"
46
+ - framework: "vue-i18n"
47
+ guidance: "Convert $t() calls to useIntl().formatMessage(); convert named interpolation to ICU syntax; move from SFC i18n blocks to centralized message files"
@@ -0,0 +1,47 @@
1
+ name: "Vue I18n"
2
+ description: "Internationalization plugin for Vue.js with SFC support and composition API integration"
3
+ platforms: ["web"]
4
+ message_format: "icu"
5
+
6
+ detection:
7
+ package_json_keys:
8
+ dependencies: ["vue-i18n", "@intlify/vue-i18n-extensions", "@intlify/unplugin-vue-i18n"]
9
+ devDependencies: ["@intlify/vite-plugin-vue-i18n", "@intlify/eslint-plugin-vue-i18n"]
10
+ file_patterns: ["src/**/*.vue", "src/locales/**/*.{json,yaml}"]
11
+ config_files: ["vue-i18n.config.ts", "i18n.ts"]
12
+
13
+ conventions:
14
+ key_format: "dot-notation"
15
+ file_format: "json"
16
+ file_structure: "src/locales/{locale}.json"
17
+ plural_syntax: "ICU {count, plural, one {# item} other {# items}} or pipe syntax: item | items"
18
+ interpolation_syntax: "{variable} or @:key for linked messages"
19
+
20
+ recommended_tooling:
21
+ extraction: ["@intlify/cli"]
22
+ linting: ["@intlify/eslint-plugin-vue-i18n"]
23
+ pseudo_locale: ["custom generator with vue-i18n message compiler"]
24
+
25
+ anti_patterns:
26
+ - pattern: "Using v-html with translated strings"
27
+ severity: error
28
+ instead: "Use the <i18n-t> component with named slots for HTML in translations — v-html creates XSS risk"
29
+ - pattern: "Hardcoding messages in template attributes"
30
+ severity: warning
31
+ instead: "Use $t() in attribute bindings: :placeholder=\"$t('search.placeholder')\" instead of hardcoded strings"
32
+ - pattern: "Not using SFC <i18n> blocks for component-local messages"
33
+ severity: info
34
+ instead: "Put component-specific messages in <i18n> blocks to co-locate translations with the component"
35
+ - pattern: "Ignoring SSR hydration mismatch with locale detection"
36
+ severity: error
37
+ instead: "Detect locale server-side (Accept-Language header) and pass to client to prevent hydration mismatch"
38
+ - pattern: "Using legacy API ($t) in Composition API components"
39
+ severity: warning
40
+ instead: "Use useI18n() composable in <script setup> components for type-safe translation access"
41
+
42
+ migration_notes:
43
+ from:
44
+ - framework: "vue-i18n v8 (Vue 2)"
45
+ guidance: "Migrate from VueI18n class to createI18n(); update $t() to useI18n().t() in Composition API; convert <i18n> blocks to new format"
46
+ - framework: "i18next"
47
+ guidance: "Convert {{variable}} to {variable}; map namespaces to vue-i18n scoped messages; replace useTranslation() with useI18n()"
@@ -0,0 +1,66 @@
1
+ name: "Ecommerce"
2
+ description: "i18n challenges in ecommerce — address formats, measurement units, tax display, and payment localization across markets"
3
+
4
+ requirements:
5
+ - area: "Address Format"
6
+ description: "Address field order and content varies dramatically by country — Japan puts postal code first, US puts it last"
7
+ severity: error
8
+ locales_affected: "all"
9
+ examples:
10
+ - bad: "Fixed form: Street, City, State, Zip, Country"
11
+ good: "Use Google's libaddressinput or similar to render country-specific address forms"
12
+ - area: "Measurement Units"
13
+ description: "Product dimensions, weight, and volume must display in locale-expected units"
14
+ severity: warning
15
+ locales_affected: "all"
16
+ examples:
17
+ - bad: "Showing all dimensions in inches regardless of locale"
18
+ good: "Display metric units (cm, kg, L) for most locales; imperial (in, lb, fl oz) for US/UK where expected"
19
+ - area: "Tax Display"
20
+ description: "VAT-inclusive (most of world) vs tax-exclusive (US) pricing causes confusion if not handled per locale"
21
+ severity: error
22
+ locales_affected: "all"
23
+ examples:
24
+ - bad: "Showing $99.99 without indicating whether tax is included"
25
+ good: "Show 'incl. VAT' for EU locales, separate tax line for US locales, GST-inclusive for AU/NZ"
26
+ - area: "Phone Number Formatting"
27
+ description: "Phone number input and display must support international formats"
28
+ severity: warning
29
+ locales_affected: "all"
30
+ examples:
31
+ - bad: "Validating phone with regex: /^\\d{10}$/"
32
+ good: "Use libphonenumber for validation and formatting; store in E.164 format (+1234567890)"
33
+ - area: "Sizing Charts"
34
+ description: "Clothing and shoe sizes vary by country — US 8 is EU 38 for women's shoes"
35
+ severity: warning
36
+ locales_affected: "all"
37
+ examples:
38
+ - bad: "Showing only US sizes for international customers"
39
+ good: "Display size conversion charts; show locale-primary sizing with equivalents"
40
+
41
+ anti_patterns:
42
+ - pattern: "Hardcoding address field order"
43
+ reason: "Japan: postal-code, prefecture, city, street; Germany: street, postal-code city; varied worldwide"
44
+ instead: "Use a country-aware address component that adapts field order per shipping country"
45
+ - pattern: "Validating postal codes with a single regex"
46
+ reason: "Postal code formats range from 5 digits (US) to alphanumeric (UK: SW1A 1AA) to none (Ireland historically)"
47
+ instead: "Use country-specific postal code validation or a library like i18n-postal-code"
48
+ - pattern: "Displaying prices without currency context"
49
+ reason: "$99 is ambiguous — USD, CAD, AUD, and others use $; customer may see wrong currency"
50
+ instead: "Always show the currency code or unambiguous symbol; use Intl.NumberFormat with currency"
51
+ - pattern: "Shipping method names not localized"
52
+ reason: "'2-Day Shipping' is meaningless outside the origin country's postal system"
53
+ instead: "Show estimated delivery date instead of carrier-specific service names"
54
+
55
+ regulations:
56
+ - name: "EU Consumer Rights Directive"
57
+ locales: ["EU member states"]
58
+ impact: "Prices must be displayed inclusive of VAT in the currency of the target market"
59
+ - name: "GDPR"
60
+ locales: ["EU member states"]
61
+ impact: "Privacy policy and consent language must be in the user's language and legally accurate per jurisdiction"
62
+ - name: "California Consumer Privacy Act (CCPA)"
63
+ locales: ["en-US"]
64
+ impact: "Privacy notices must be accessible; consider multilingual California population"
65
+
66
+ reference_products: ["shopify.com", "amazon.com", "etsy.com", "zalando.com"]
@@ -0,0 +1,66 @@
1
+ name: "Fintech"
2
+ description: "i18n challenges in financial technology — currency precision, number formatting, and regulatory compliance across markets"
3
+
4
+ requirements:
5
+ - area: "Currency Display"
6
+ description: "Currency formatting varies by locale — symbol position, decimal precision, and grouping separators differ"
7
+ severity: error
8
+ locales_affected: "all"
9
+ examples:
10
+ - bad: "'$' + amount.toFixed(2)"
11
+ good: "new Intl.NumberFormat(locale, { style: 'currency', currency: currencyCode }).format(amount)"
12
+ - area: "Currency Precision"
13
+ description: "Decimal places vary by currency — JPY has 0, USD/EUR have 2, BHD/KWD have 3"
14
+ severity: error
15
+ locales_affected: "all"
16
+ examples:
17
+ - bad: "amount.toFixed(2) for all currencies"
18
+ good: "Use Intl.NumberFormat with currency option which auto-selects correct decimal places"
19
+ - area: "Number Formatting"
20
+ description: "Thousands separators and decimal points vary — 1,234.56 (en) vs 1.234,56 (de) vs 1 234,56 (fr)"
21
+ severity: error
22
+ locales_affected: "all"
23
+ examples:
24
+ - bad: "amount.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')"
25
+ good: "new Intl.NumberFormat(locale).format(amount)"
26
+ - area: "Regulatory Date Formats"
27
+ description: "Financial regulations often mandate specific date formats — ambiguous dates (01/02/2025) cause compliance issues"
28
+ severity: error
29
+ locales_affected: "all"
30
+ examples:
31
+ - bad: "01/02/2025 (is this Jan 2 or Feb 1?)"
32
+ good: "Use unambiguous formats (2025-01-02) for regulatory documents; locale-specific for user display"
33
+ - area: "Financial Amount Display"
34
+ description: "Negative amounts, accounting notation, and color coding must follow locale conventions"
35
+ severity: warning
36
+ locales_affected: "all"
37
+ examples:
38
+ - bad: "Showing -$1,234.56 in all locales"
39
+ good: "Use Intl.NumberFormat with signDisplay and currencySign: 'accounting' for locale-correct negative display"
40
+
41
+ anti_patterns:
42
+ - pattern: "Hardcoding currency symbol position"
43
+ reason: "Symbol placement varies: $100 (en-US), 100$ (fr-CA), 100 $ (fr-FR)"
44
+ instead: "Use Intl.NumberFormat with currency style which handles symbol placement per locale"
45
+ - pattern: "Converting currencies with hardcoded exchange rates"
46
+ reason: "Exchange rates change constantly; stale rates in code cause incorrect financial displays"
47
+ instead: "Fetch exchange rates from a reliable API; cache with appropriate TTL"
48
+ - pattern: "Using floating point for financial calculations"
49
+ reason: "IEEE 754 floating point causes rounding errors: 0.1 + 0.2 !== 0.3"
50
+ instead: "Use integer arithmetic in smallest currency unit (cents) or a decimal library"
51
+ - pattern: "Displaying amounts without locale-specific accounting format"
52
+ reason: "Negative amounts display differently: -$100 (US), ($100) (accounting), -100$ (other locales)"
53
+ instead: "Use Intl.NumberFormat with currencySign: 'accounting' for financial contexts"
54
+
55
+ regulations:
56
+ - name: "PSD2 (Payment Services Directive 2)"
57
+ locales: ["EU member states"]
58
+ impact: "Transaction amounts must be displayed in the customer's local currency with correct formatting"
59
+ - name: "MiFID II"
60
+ locales: ["EU member states"]
61
+ impact: "Financial documents must show costs in the client's preferred currency with mandated precision"
62
+ - name: "RBI Guidelines"
63
+ locales: ["hi", "en-IN"]
64
+ impact: "Indian Rupee amounts must use Indian number grouping (lakhs/crores) in customer-facing displays"
65
+
66
+ reference_products: ["wise.com", "stripe.com", "revolut.com", "mercury.com"]
@@ -0,0 +1,69 @@
1
+ name: "Gaming"
2
+ description: "i18n challenges in gaming — character limits in UI, cultural adaptation, rating systems, and in-game text rendering"
3
+
4
+ requirements:
5
+ - area: "Character Limits in HUD/UI"
6
+ description: "Game HUDs and menus have fixed-width pixel budgets — translated text must fit without overflow"
7
+ severity: error
8
+ locales_affected: "all"
9
+ examples:
10
+ - bad: "Fixed 120px button with English text 'Attack' that becomes 'Angreifen' (German, does not fit)"
11
+ good: "Design UI with flexible text containers or set per-locale character limits with translator guidance"
12
+ - area: "Cultural Adaptation"
13
+ description: "Colors, gestures, symbols, and themes have different meanings across cultures"
14
+ severity: warning
15
+ locales_affected: "all"
16
+ examples:
17
+ - bad: "Using white for death/mourning themes globally (white = mourning in East Asia, black in Western cultures)"
18
+ good: "Audit cultural symbols and adapt color meanings, gestures, and imagery per target market"
19
+ - area: "Rating Systems"
20
+ description: "Age ratings differ by region — ESRB (US), PEGI (EU), CERO (JP), USK (DE) have different criteria"
21
+ severity: error
22
+ locales_affected: "all"
23
+ examples:
24
+ - bad: "Showing ESRB rating to European players"
25
+ good: "Display the correct regional rating system with proper locale-specific rating icons and descriptions"
26
+ - area: "In-Game Text Rendering"
27
+ description: "Bitmap fonts may not support all scripts; dynamic text needs proper shaping for CJK, Arabic, Devanagari"
28
+ severity: error
29
+ locales_affected: ["ja", "zh-Hans", "zh-Hant", "ko", "ar", "he", "hi", "th"]
30
+ examples:
31
+ - bad: "Using a bitmap font that only contains Latin glyphs for all locales"
32
+ good: "Use Unicode-capable font rendering or locale-specific bitmap fonts with full glyph coverage"
33
+ - area: "Voiceover and Subtitle Synchronization"
34
+ description: "Dubbed audio and subtitles must match game timing — translated dialogue may be longer or shorter"
35
+ severity: warning
36
+ locales_affected: "all"
37
+ examples:
38
+ - bad: "Subtitles that flash too quickly because translated text is longer than English source"
39
+ good: "Adjust subtitle display timing based on translated text length; allow subtitle speed settings"
40
+
41
+ anti_patterns:
42
+ - pattern: "Hardcoding text in texture/sprite assets"
43
+ reason: "Text baked into images cannot be translated without re-creating the entire asset per locale"
44
+ instead: "Render text dynamically over images; use text layers separate from background art"
45
+ - pattern: "Concatenating strings for item descriptions"
46
+ reason: "'Legendary' + 'Sword' + 'of Fire' — word order changes by language, adjective placement varies"
47
+ instead: "Use complete translatable strings: '{quality} {weapon} {element}' with locale-aware ordering"
48
+ - pattern: "Assuming left-to-right menu navigation for all locales"
49
+ reason: "Arabic and Hebrew players expect RTL menu flow and mirrored UI layouts"
50
+ instead: "Mirror the full game UI for RTL locales including menus, HUD, and inventory screens"
51
+ - pattern: "Using player-facing dates without locale formatting"
52
+ reason: "Event dates like '12/1' are ambiguous — December 1 or January 12 depending on locale"
53
+ instead: "Use locale-aware date formatting or unambiguous formats with month names for in-game events"
54
+ - pattern: "Embedding culturally specific humor or idioms"
55
+ reason: "Jokes and idioms rarely translate directly — they fall flat or cause offense in other cultures"
56
+ instead: "Flag humor/idioms for cultural adaptation (not just translation) in localization notes"
57
+
58
+ regulations:
59
+ - name: "ESRB (Entertainment Software Rating Board)"
60
+ locales: ["en-US", "en-CA"]
61
+ impact: "Content descriptors and rating labels must be in English; may require Spanish for US market"
62
+ - name: "PEGI (Pan European Game Information)"
63
+ locales: ["EU member states"]
64
+ impact: "Rating icons and content descriptors must follow PEGI standards; some content prohibited in certain countries"
65
+ - name: "CERO (Computer Entertainment Rating Organization)"
66
+ locales: ["ja"]
67
+ impact: "Japanese rating system with different thresholds; some content requires modification for Japan market"
68
+
69
+ reference_products: ["store.steampowered.com", "playstation.com", "xbox.com", "nintendo.com"]