@pie-players/pie-players-shared 0.2.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 (233) hide show
  1. package/dist/config/profile.d.ts +15 -0
  2. package/dist/config/profile.d.ts.map +1 -0
  3. package/dist/config/profile.js +27 -0
  4. package/dist/config/profile.js.map +1 -0
  5. package/dist/i18n/index.d.ts +13 -0
  6. package/dist/i18n/index.d.ts.map +1 -0
  7. package/dist/i18n/index.js +12 -0
  8. package/dist/i18n/index.js.map +1 -0
  9. package/dist/i18n/loader.d.ts +36 -0
  10. package/dist/i18n/loader.d.ts.map +1 -0
  11. package/dist/i18n/loader.js +133 -0
  12. package/dist/i18n/loader.js.map +1 -0
  13. package/dist/i18n/scripts/check-coverage.d.ts +16 -0
  14. package/dist/i18n/scripts/check-coverage.d.ts.map +1 -0
  15. package/dist/i18n/scripts/check-coverage.js +262 -0
  16. package/dist/i18n/scripts/check-coverage.js.map +1 -0
  17. package/dist/i18n/scripts/scan-hardcoded.d.ts +16 -0
  18. package/dist/i18n/scripts/scan-hardcoded.d.ts.map +1 -0
  19. package/dist/i18n/scripts/scan-hardcoded.js +266 -0
  20. package/dist/i18n/scripts/scan-hardcoded.js.map +1 -0
  21. package/dist/i18n/simple-i18n.d.ts +69 -0
  22. package/dist/i18n/simple-i18n.d.ts.map +1 -0
  23. package/dist/i18n/simple-i18n.js +199 -0
  24. package/dist/i18n/simple-i18n.js.map +1 -0
  25. package/dist/i18n/translations/ar/common.json +36 -0
  26. package/dist/i18n/translations/ar/toolkit.json +48 -0
  27. package/dist/i18n/translations/ar/tools.json +109 -0
  28. package/dist/i18n/translations/en/common.json +36 -0
  29. package/dist/i18n/translations/en/toolkit.json +48 -0
  30. package/dist/i18n/translations/en/tools.json +109 -0
  31. package/dist/i18n/translations/es/common.json +36 -0
  32. package/dist/i18n/translations/es/toolkit.json +48 -0
  33. package/dist/i18n/translations/es/tools.json +109 -0
  34. package/dist/i18n/translations/zh/common.json +36 -0
  35. package/dist/i18n/translations/zh/toolkit.json +48 -0
  36. package/dist/i18n/translations/zh/tools.json +109 -0
  37. package/dist/i18n/types.d.ts +58 -0
  38. package/dist/i18n/types.d.ts.map +1 -0
  39. package/dist/i18n/types.js +8 -0
  40. package/dist/i18n/types.js.map +1 -0
  41. package/dist/i18n/use-i18n-standalone.svelte.d.ts +87 -0
  42. package/dist/i18n/use-i18n-standalone.svelte.d.ts.map +1 -0
  43. package/dist/i18n/use-i18n-standalone.svelte.js +151 -0
  44. package/dist/i18n/use-i18n-standalone.svelte.js.map +1 -0
  45. package/dist/i18n/use-i18n.svelte.d.ts +67 -0
  46. package/dist/i18n/use-i18n.svelte.d.ts.map +1 -0
  47. package/dist/i18n/use-i18n.svelte.js +144 -0
  48. package/dist/i18n/use-i18n.svelte.js.map +1 -0
  49. package/dist/index.d.ts +11 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +11 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/instrumentation/index.d.ts +53 -0
  54. package/dist/instrumentation/index.d.ts.map +1 -0
  55. package/dist/instrumentation/index.js +53 -0
  56. package/dist/instrumentation/index.js.map +1 -0
  57. package/dist/instrumentation/providers/BaseInstrumentationProvider.d.ts +197 -0
  58. package/dist/instrumentation/providers/BaseInstrumentationProvider.d.ts.map +1 -0
  59. package/dist/instrumentation/providers/BaseInstrumentationProvider.js +267 -0
  60. package/dist/instrumentation/providers/BaseInstrumentationProvider.js.map +1 -0
  61. package/dist/instrumentation/providers/ConsoleInstrumentationProvider.d.ts +106 -0
  62. package/dist/instrumentation/providers/ConsoleInstrumentationProvider.d.ts.map +1 -0
  63. package/dist/instrumentation/providers/ConsoleInstrumentationProvider.js +182 -0
  64. package/dist/instrumentation/providers/ConsoleInstrumentationProvider.js.map +1 -0
  65. package/dist/instrumentation/providers/DataDogInstrumentationProvider.d.ts +170 -0
  66. package/dist/instrumentation/providers/DataDogInstrumentationProvider.d.ts.map +1 -0
  67. package/dist/instrumentation/providers/DataDogInstrumentationProvider.js +183 -0
  68. package/dist/instrumentation/providers/DataDogInstrumentationProvider.js.map +1 -0
  69. package/dist/instrumentation/providers/NewRelicInstrumentationProvider.d.ts +86 -0
  70. package/dist/instrumentation/providers/NewRelicInstrumentationProvider.d.ts.map +1 -0
  71. package/dist/instrumentation/providers/NewRelicInstrumentationProvider.js +135 -0
  72. package/dist/instrumentation/providers/NewRelicInstrumentationProvider.js.map +1 -0
  73. package/dist/instrumentation/providers/index.d.ts +12 -0
  74. package/dist/instrumentation/providers/index.d.ts.map +1 -0
  75. package/dist/instrumentation/providers/index.js +12 -0
  76. package/dist/instrumentation/providers/index.js.map +1 -0
  77. package/dist/instrumentation/types.d.ts +348 -0
  78. package/dist/instrumentation/types.d.ts.map +1 -0
  79. package/dist/instrumentation/types.js +9 -0
  80. package/dist/instrumentation/types.js.map +1 -0
  81. package/dist/loader-config.d.ts +76 -0
  82. package/dist/loader-config.d.ts.map +1 -0
  83. package/dist/loader-config.js +12 -0
  84. package/dist/loader-config.js.map +1 -0
  85. package/dist/loaders/ElementLoader.d.ts +72 -0
  86. package/dist/loaders/ElementLoader.d.ts.map +1 -0
  87. package/dist/loaders/ElementLoader.js +52 -0
  88. package/dist/loaders/ElementLoader.js.map +1 -0
  89. package/dist/loaders/EsmElementLoader.d.ts +67 -0
  90. package/dist/loaders/EsmElementLoader.d.ts.map +1 -0
  91. package/dist/loaders/EsmElementLoader.js +71 -0
  92. package/dist/loaders/EsmElementLoader.js.map +1 -0
  93. package/dist/loaders/IifeElementLoader.d.ts +61 -0
  94. package/dist/loaders/IifeElementLoader.d.ts.map +1 -0
  95. package/dist/loaders/IifeElementLoader.js +63 -0
  96. package/dist/loaders/IifeElementLoader.js.map +1 -0
  97. package/dist/loaders/index.d.ts +28 -0
  98. package/dist/loaders/index.d.ts.map +1 -0
  99. package/dist/loaders/index.js +25 -0
  100. package/dist/loaders/index.js.map +1 -0
  101. package/dist/object/index.d.ts +12 -0
  102. package/dist/object/index.d.ts.map +1 -0
  103. package/dist/object/index.js +40 -0
  104. package/dist/object/index.js.map +1 -0
  105. package/dist/pie/asset-handler.d.ts +64 -0
  106. package/dist/pie/asset-handler.d.ts.map +1 -0
  107. package/dist/pie/asset-handler.js +238 -0
  108. package/dist/pie/asset-handler.js.map +1 -0
  109. package/dist/pie/component-context.d.ts +22 -0
  110. package/dist/pie/component-context.d.ts.map +1 -0
  111. package/dist/pie/component-context.js +30 -0
  112. package/dist/pie/component-context.js.map +1 -0
  113. package/dist/pie/config.d.ts +39 -0
  114. package/dist/pie/config.d.ts.map +1 -0
  115. package/dist/pie/config.js +174 -0
  116. package/dist/pie/config.js.map +1 -0
  117. package/dist/pie/configure-initialization.d.ts +35 -0
  118. package/dist/pie/configure-initialization.d.ts.map +1 -0
  119. package/dist/pie/configure-initialization.js +141 -0
  120. package/dist/pie/configure-initialization.js.map +1 -0
  121. package/dist/pie/esm-loader.d.ts +93 -0
  122. package/dist/pie/esm-loader.d.ts.map +1 -0
  123. package/dist/pie/esm-loader.js +308 -0
  124. package/dist/pie/esm-loader.js.map +1 -0
  125. package/dist/pie/iife-loader.d.ts +76 -0
  126. package/dist/pie/iife-loader.d.ts.map +1 -0
  127. package/dist/pie/iife-loader.js +303 -0
  128. package/dist/pie/iife-loader.js.map +1 -0
  129. package/dist/pie/index.d.ts +31 -0
  130. package/dist/pie/index.d.ts.map +1 -0
  131. package/dist/pie/index.js +34 -0
  132. package/dist/pie/index.js.map +1 -0
  133. package/dist/pie/initialization.d.ts +40 -0
  134. package/dist/pie/initialization.d.ts.map +1 -0
  135. package/dist/pie/initialization.js +349 -0
  136. package/dist/pie/initialization.js.map +1 -0
  137. package/dist/pie/logger.d.ts +64 -0
  138. package/dist/pie/logger.d.ts.map +1 -0
  139. package/dist/pie/logger.js +45 -0
  140. package/dist/pie/logger.js.map +1 -0
  141. package/dist/pie/math-rendering.d.ts +69 -0
  142. package/dist/pie/math-rendering.d.ts.map +1 -0
  143. package/dist/pie/math-rendering.js +98 -0
  144. package/dist/pie/math-rendering.js.map +1 -0
  145. package/dist/pie/overrides.d.ts +43 -0
  146. package/dist/pie/overrides.d.ts.map +1 -0
  147. package/dist/pie/overrides.js +146 -0
  148. package/dist/pie/overrides.js.map +1 -0
  149. package/dist/pie/player-initializer.d.ts +55 -0
  150. package/dist/pie/player-initializer.d.ts.map +1 -0
  151. package/dist/pie/player-initializer.js +123 -0
  152. package/dist/pie/player-initializer.js.map +1 -0
  153. package/dist/pie/registry.d.ts +11 -0
  154. package/dist/pie/registry.d.ts.map +1 -0
  155. package/dist/pie/registry.js +21 -0
  156. package/dist/pie/registry.js.map +1 -0
  157. package/dist/pie/resource-monitor.d.ts +208 -0
  158. package/dist/pie/resource-monitor.d.ts.map +1 -0
  159. package/dist/pie/resource-monitor.js +969 -0
  160. package/dist/pie/resource-monitor.js.map +1 -0
  161. package/dist/pie/scoring.d.ts +17 -0
  162. package/dist/pie/scoring.d.ts.map +1 -0
  163. package/dist/pie/scoring.js +84 -0
  164. package/dist/pie/scoring.js.map +1 -0
  165. package/dist/pie/types.d.ts +136 -0
  166. package/dist/pie/types.d.ts.map +1 -0
  167. package/dist/pie/types.js +52 -0
  168. package/dist/pie/types.js.map +1 -0
  169. package/dist/pie/updates.d.ts +20 -0
  170. package/dist/pie/updates.d.ts.map +1 -0
  171. package/dist/pie/updates.js +175 -0
  172. package/dist/pie/updates.js.map +1 -0
  173. package/dist/pie/use-resource-monitor.svelte.d.ts +56 -0
  174. package/dist/pie/use-resource-monitor.svelte.d.ts.map +1 -0
  175. package/dist/pie/use-resource-monitor.svelte.js +117 -0
  176. package/dist/pie/use-resource-monitor.svelte.js.map +1 -0
  177. package/dist/pie/utils.d.ts +44 -0
  178. package/dist/pie/utils.d.ts.map +1 -0
  179. package/dist/pie/utils.js +74 -0
  180. package/dist/pie/utils.js.map +1 -0
  181. package/dist/types/custom-elements.d.ts +183 -0
  182. package/dist/types/custom-elements.d.ts.map +1 -0
  183. package/dist/types/custom-elements.js +8 -0
  184. package/dist/types/custom-elements.js.map +1 -0
  185. package/dist/types/index.d.ts +761 -0
  186. package/dist/types/index.d.ts.map +1 -0
  187. package/dist/types/index.js +120 -0
  188. package/dist/types/index.js.map +1 -0
  189. package/dist/types/search.d.ts +105 -0
  190. package/dist/types/search.d.ts.map +1 -0
  191. package/dist/types/search.js +12 -0
  192. package/dist/types/search.js.map +1 -0
  193. package/dist/types/transform.d.ts +48 -0
  194. package/dist/types/transform.d.ts.map +1 -0
  195. package/dist/types/transform.js +21 -0
  196. package/dist/types/transform.js.map +1 -0
  197. package/dist/ui/focus-trap.d.ts +10 -0
  198. package/dist/ui/focus-trap.d.ts.map +1 -0
  199. package/dist/ui/focus-trap.js +30 -0
  200. package/dist/ui/focus-trap.js.map +1 -0
  201. package/dist/ui/safe-storage.d.ts +3 -0
  202. package/dist/ui/safe-storage.d.ts.map +1 -0
  203. package/dist/ui/safe-storage.js +21 -0
  204. package/dist/ui/safe-storage.js.map +1 -0
  205. package/package.json +118 -0
  206. package/src/components/PieItemPlayer.svelte +604 -0
  207. package/src/components/PiePreviewLayout.svelte +144 -0
  208. package/src/components/PiePreviewToggle.svelte +110 -0
  209. package/src/components/PieSpinner.svelte +85 -0
  210. package/src/components/ToolSettingsButton.svelte +31 -0
  211. package/src/components/ToolSettingsPanel.svelte +90 -0
  212. package/src/components/index.ts +6 -0
  213. package/src/i18n/README.md +223 -0
  214. package/src/i18n/index.ts +26 -0
  215. package/src/i18n/loader.ts +156 -0
  216. package/src/i18n/scripts/check-coverage.ts +345 -0
  217. package/src/i18n/scripts/scan-hardcoded.ts +342 -0
  218. package/src/i18n/simple-i18n.ts +236 -0
  219. package/src/i18n/translations/ar/common.json +36 -0
  220. package/src/i18n/translations/ar/toolkit.json +48 -0
  221. package/src/i18n/translations/ar/tools.json +109 -0
  222. package/src/i18n/translations/en/common.json +36 -0
  223. package/src/i18n/translations/en/toolkit.json +48 -0
  224. package/src/i18n/translations/en/tools.json +109 -0
  225. package/src/i18n/translations/es/common.json +36 -0
  226. package/src/i18n/translations/es/toolkit.json +48 -0
  227. package/src/i18n/translations/es/tools.json +109 -0
  228. package/src/i18n/translations/zh/common.json +36 -0
  229. package/src/i18n/translations/zh/toolkit.json +48 -0
  230. package/src/i18n/translations/zh/tools.json +109 -0
  231. package/src/i18n/types.ts +66 -0
  232. package/src/i18n/use-i18n-standalone.svelte.ts +184 -0
  233. package/src/i18n/use-i18n.svelte.ts +163 -0
@@ -0,0 +1,266 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Hardcoded String Scanner
4
+ *
5
+ * Scans component files for hardcoded English strings that should use i18n.
6
+ * Adapted from pie-qti's hardcoded string scanner.
7
+ *
8
+ * Usage:
9
+ * bun run packages/players-shared/src/i18n/scripts/scan-hardcoded.ts
10
+ *
11
+ * Options:
12
+ * --path <dir> - Directory to scan (default: packages/)
13
+ * --fix - Attempt to auto-fix issues (not implemented yet)
14
+ */
15
+ import { readFileSync } from "fs";
16
+ import { glob } from "glob";
17
+ import { dirname, relative, resolve } from "path";
18
+ import { fileURLToPath } from "url";
19
+ const __filename = fileURLToPath(import.meta.url);
20
+ const __dirname = dirname(__filename);
21
+ /**
22
+ * Load all English translations
23
+ */
24
+ function loadEnglishTranslations() {
25
+ const basePath = resolve(__dirname, "../translations/en");
26
+ const translations = {};
27
+ try {
28
+ const common = JSON.parse(readFileSync(resolve(basePath, "common.json"), "utf-8"));
29
+ const toolkit = JSON.parse(readFileSync(resolve(basePath, "toolkit.json"), "utf-8"));
30
+ const tools = JSON.parse(readFileSync(resolve(basePath, "tools.json"), "utf-8"));
31
+ // Flatten all translations
32
+ flattenObject(common, "", translations);
33
+ flattenObject(toolkit, "", translations);
34
+ flattenObject(tools, "", translations);
35
+ }
36
+ catch (error) {
37
+ console.error("Error loading English translations:", error);
38
+ throw error;
39
+ }
40
+ return translations;
41
+ }
42
+ /**
43
+ * Flatten nested object to dot notation
44
+ */
45
+ function flattenObject(obj, prefix, result) {
46
+ for (const [key, value] of Object.entries(obj)) {
47
+ const fullKey = prefix ? `${prefix}.${key}` : key;
48
+ if (typeof value === "object" && value !== null) {
49
+ // Check for plural form
50
+ if ("one" in value && "other" in value) {
51
+ result[fullKey] = value.one;
52
+ }
53
+ else {
54
+ flattenObject(value, fullKey, result);
55
+ }
56
+ }
57
+ else if (typeof value === "string") {
58
+ result[fullKey] = value;
59
+ }
60
+ }
61
+ }
62
+ /**
63
+ * Find translation key for a given string value
64
+ */
65
+ function findTranslationKey(translations, searchValue) {
66
+ // Exact match first
67
+ for (const [key, value] of Object.entries(translations)) {
68
+ if (value === searchValue) {
69
+ return key;
70
+ }
71
+ }
72
+ // Fuzzy match (case-insensitive)
73
+ const lowerSearch = searchValue.toLowerCase();
74
+ for (const [key, value] of Object.entries(translations)) {
75
+ if (value.toLowerCase() === lowerSearch) {
76
+ return key;
77
+ }
78
+ }
79
+ return null;
80
+ }
81
+ /**
82
+ * Scan a file for hardcoded strings
83
+ */
84
+ function scanFile(filePath, translations) {
85
+ const content = readFileSync(filePath, "utf-8");
86
+ const lines = content.split("\n");
87
+ const matches = [];
88
+ // Patterns to match quoted English strings
89
+ // Matches: "Text", 'Text', but ignores: i18n.t(...), class="...", etc.
90
+ const stringPattern = /["']([A-Z][A-Za-z\s,.:;!?'\-()]+)["']/g;
91
+ // Patterns to exclude (already using i18n, CSS classes, imports, etc.)
92
+ const excludePatterns = [
93
+ /i18n\./,
94
+ /import\s+/,
95
+ /from\s+['"]/,
96
+ /class[:=]/,
97
+ /className[:=]/,
98
+ /aria-\w+[:=]/,
99
+ /data-\w+[:=]/,
100
+ /id[:=]/,
101
+ /key[:=]/,
102
+ /name[:=]/,
103
+ /type[:=]/,
104
+ /href[:=]/,
105
+ /src[:=]/,
106
+ /alt[:=]/,
107
+ /title[:=]/,
108
+ /placeholder[:=]/,
109
+ /console\./,
110
+ /\/\//, // Comments
111
+ /\/\*/, // Block comments
112
+ ];
113
+ lines.forEach((line, index) => {
114
+ // Skip lines that match exclude patterns
115
+ if (excludePatterns.some((pattern) => pattern.test(line))) {
116
+ return;
117
+ }
118
+ // Find all string matches in the line
119
+ let match;
120
+ while ((match = stringPattern.exec(line)) !== null) {
121
+ const string = match[1];
122
+ // Skip very short strings (likely not user-facing)
123
+ if (string.length < 3)
124
+ continue;
125
+ // Skip strings that are mostly numbers or special characters
126
+ if (!/[a-zA-Z]{3,}/.test(string))
127
+ continue;
128
+ // Find corresponding translation key
129
+ const suggestedKey = findTranslationKey(translations, string);
130
+ matches.push({
131
+ file: filePath,
132
+ line: index + 1,
133
+ context: line.trim(),
134
+ string,
135
+ suggestedKey,
136
+ });
137
+ }
138
+ });
139
+ return matches;
140
+ }
141
+ /**
142
+ * Format scan results
143
+ */
144
+ function formatResults(matchesByFile, rootDir) {
145
+ let report = "\n";
146
+ report += "┌─────────────────────────────────────────────────────┐\n";
147
+ report += "│ Hardcoded String Scanner │\n";
148
+ report += "└─────────────────────────────────────────────────────┘\n\n";
149
+ const fileCount = matchesByFile.size;
150
+ const totalMatches = Array.from(matchesByFile.values()).reduce((sum, m) => sum + m.length, 0);
151
+ if (fileCount === 0) {
152
+ report += "✅ No hardcoded strings found!\n\n";
153
+ return report;
154
+ }
155
+ // Sort files by number of matches (descending)
156
+ const sortedFiles = Array.from(matchesByFile.entries()).sort((a, b) => b[1].length - a[1].length);
157
+ for (const [file, matches] of sortedFiles) {
158
+ const relPath = relative(rootDir, file);
159
+ report += `📄 ${relPath} (${matches.length} match${matches.length === 1 ? "" : "es"})\n`;
160
+ report += "────────────────────────────────────────────────────────\n";
161
+ for (const match of matches) {
162
+ report += ` Line ${match.line}: ${match.context}\n`;
163
+ report += ` Found: "${match.string}"\n`;
164
+ if (match.suggestedKey) {
165
+ report += ` Use: i18n?.t('${match.suggestedKey}') ?? '${match.suggestedKey}'\n`;
166
+ }
167
+ else {
168
+ report += ` Note: No matching translation key found. Consider adding to translations.\n`;
169
+ }
170
+ report += "\n";
171
+ }
172
+ report += "\n";
173
+ }
174
+ report += "════════════════════════════════════════════════════════\n";
175
+ report += "📊 Summary:\n";
176
+ report += "────────────────────────────────────────────────────────\n";
177
+ report += ` Total files scanned: ${fileCount}\n`;
178
+ report += ` Files with matches: ${fileCount}\n`;
179
+ report += ` Total hardcoded strings: ${totalMatches}\n\n`;
180
+ report += "⚠️ Recommendation: Replace hardcoded strings with i18n keys\n";
181
+ report += " for proper internationalization support.\n";
182
+ report += "════════════════════════════════════════════════════════\n";
183
+ return report;
184
+ }
185
+ /**
186
+ * Find project root by looking for package.json with workspaces
187
+ */
188
+ function findProjectRoot() {
189
+ let currentDir = process.cwd();
190
+ while (currentDir !== "/") {
191
+ try {
192
+ const pkgPath = resolve(currentDir, "package.json");
193
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
194
+ if (pkg.workspaces) {
195
+ return currentDir;
196
+ }
197
+ }
198
+ catch {
199
+ // Continue searching
200
+ }
201
+ currentDir = dirname(currentDir);
202
+ }
203
+ // Fallback to script location's root
204
+ return resolve(__dirname, "../../../..");
205
+ }
206
+ /**
207
+ * Main entry point
208
+ */
209
+ async function main() {
210
+ const args = process.argv.slice(2);
211
+ const pathArg = args.indexOf("--path");
212
+ // Find project root and default to scanning packages/
213
+ const projectRoot = findProjectRoot();
214
+ const defaultPath = resolve(projectRoot, "packages/");
215
+ const scanPath = pathArg !== -1 ? resolve(projectRoot, args[pathArg + 1]) : defaultPath;
216
+ console.log("🔍 Scanning for hardcoded strings...\n");
217
+ console.log(`📂 Scan path: ${scanPath}\n`);
218
+ try {
219
+ // Load English translations for matching
220
+ const translations = loadEnglishTranslations();
221
+ console.log(`📖 Loaded ${Object.keys(translations).length} translation keys\n`);
222
+ // Find all component files
223
+ const allFiles = await glob(`${scanPath}/**/*.{svelte,ts,tsx}`, {
224
+ absolute: true,
225
+ });
226
+ // Filter out unwanted directories manually
227
+ const files = allFiles.filter((file) => {
228
+ return (!file.includes("/node_modules/") &&
229
+ !file.includes("/dist/") &&
230
+ !file.includes("/.svelte-kit/") &&
231
+ !file.includes("/build/") &&
232
+ !file.endsWith(".spec.ts") &&
233
+ !file.endsWith(".test.ts") &&
234
+ !file.includes("/scripts/"));
235
+ });
236
+ console.log(`📁 Found ${files.length} files to scan\n`);
237
+ // Scan all files
238
+ const matchesByFile = new Map();
239
+ for (const file of files) {
240
+ const matches = scanFile(file, translations);
241
+ if (matches.length > 0) {
242
+ matchesByFile.set(file, matches);
243
+ }
244
+ }
245
+ // Print results
246
+ const report = formatResults(matchesByFile, projectRoot);
247
+ console.log(report);
248
+ // Exit with warning if matches found
249
+ if (matchesByFile.size > 0) {
250
+ console.warn("\n⚠️ Found hardcoded strings. Consider using i18n for these strings.\n");
251
+ // Don't exit with error - this is informational only
252
+ process.exit(0);
253
+ }
254
+ console.log("✅ No hardcoded strings found!\n");
255
+ process.exit(0);
256
+ }
257
+ catch (error) {
258
+ console.error("\n❌ Fatal error during scan:", error);
259
+ process.exit(1);
260
+ }
261
+ }
262
+ // Run if executed directly
263
+ if (import.meta.url === `file://${process.argv[1]}`) {
264
+ main();
265
+ }
266
+ //# sourceMappingURL=scan-hardcoded.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-hardcoded.js","sourceRoot":"","sources":["../../../src/i18n/scripts/scan-hardcoded.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Simple I18n Implementation
3
+ *
4
+ * Lightweight i18n without external dependencies.
5
+ * Used for standalone components that don't need the full service architecture.
6
+ */
7
+ import type { I18nConfig } from "./types";
8
+ /**
9
+ * Simple I18n class for standalone use
10
+ */
11
+ export declare class SimpleI18n {
12
+ private locale;
13
+ private fallbackLocale;
14
+ private direction;
15
+ private translations;
16
+ private listeners;
17
+ private loadingPromises;
18
+ private config;
19
+ constructor(config?: I18nConfig);
20
+ /**
21
+ * Initialize with locale
22
+ */
23
+ initialize(config: I18nConfig): Promise<void>;
24
+ /**
25
+ * Translate a key
26
+ */
27
+ t(key: string, params?: Record<string, any>): string;
28
+ /**
29
+ * Translate with pluralization
30
+ */
31
+ tn(key: string, count: number, params?: Record<string, any>): string;
32
+ /**
33
+ * Get current locale
34
+ */
35
+ getLocale(): string;
36
+ /**
37
+ * Change locale
38
+ */
39
+ setLocale(locale: string): Promise<void>;
40
+ /**
41
+ * Get current direction
42
+ */
43
+ getDirection(): "ltr" | "rtl";
44
+ /**
45
+ * Get available locales
46
+ */
47
+ getAvailableLocales(): string[];
48
+ /**
49
+ * Check if locale is loaded
50
+ */
51
+ isLocaleLoaded(locale: string): boolean;
52
+ /**
53
+ * Subscribe to changes
54
+ */
55
+ subscribe(listener: () => void): () => void;
56
+ /**
57
+ * Check if key exists
58
+ */
59
+ hasKey(key: string): boolean;
60
+ private notifyListeners;
61
+ private applyLocale;
62
+ private applyDOMDirection;
63
+ private loadTranslationsForLocale;
64
+ private getTranslation;
65
+ private interpolate;
66
+ private selectPluralForm;
67
+ private detectBrowserLocale;
68
+ }
69
+ //# sourceMappingURL=simple-i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple-i18n.d.ts","sourceRoot":"","sources":["../../src/i18n/simple-i18n.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAwC,MAAM,SAAS,CAAC;AAEhF;;GAEG;AACH,qBAAa,UAAU;IACtB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,MAAM,CAAa;gBAEf,MAAM,GAAE,UAAe;IAcnC;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnD;;OAEG;IACH,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM;IAKpD;;OAEG;IACH,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM;IAYpE;;OAEG;IACH,SAAS,IAAI,MAAM;IAInB;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB9C;;OAEG;IACH,YAAY,IAAI,KAAK,GAAG,KAAK;IAI7B;;OAEG;IACH,mBAAmB,IAAI,MAAM,EAAE;IAI/B;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIvC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAO3C;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAK5B,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,iBAAiB;YAOX,yBAAyB;IASvC,OAAO,CAAC,cAAc;IAqBtB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,mBAAmB;CAU3B"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Simple I18n Implementation
3
+ *
4
+ * Lightweight i18n without external dependencies.
5
+ * Used for standalone components that don't need the full service architecture.
6
+ */
7
+ /**
8
+ * Simple I18n class for standalone use
9
+ */
10
+ export class SimpleI18n {
11
+ locale = "en";
12
+ fallbackLocale = "en";
13
+ direction = "ltr";
14
+ translations = new Map();
15
+ listeners = new Set();
16
+ loadingPromises = new Map();
17
+ config;
18
+ constructor(config = {}) {
19
+ this.config = config;
20
+ this.fallbackLocale = config.fallbackLocale || "en";
21
+ // Load bundled translations
22
+ if (config.bundledTranslations) {
23
+ for (const [locale, bundle] of Object.entries(config.bundledTranslations)) {
24
+ this.translations.set(locale, bundle);
25
+ }
26
+ }
27
+ }
28
+ /**
29
+ * Initialize with locale
30
+ */
31
+ async initialize(config) {
32
+ Object.assign(this.config, config);
33
+ const locale = config.locale || this.detectBrowserLocale();
34
+ await this.setLocale(locale);
35
+ }
36
+ /**
37
+ * Translate a key
38
+ */
39
+ t(key, params) {
40
+ const translation = this.getTranslation(key);
41
+ return this.interpolate(translation, params);
42
+ }
43
+ /**
44
+ * Translate with pluralization
45
+ */
46
+ tn(key, count, params) {
47
+ const translation = this.getTranslation(key);
48
+ if (typeof translation === "object") {
49
+ const pluralForm = this.selectPluralForm(count, this.locale);
50
+ const text = translation[pluralForm] || translation.other;
51
+ return this.interpolate(text, { ...params, count });
52
+ }
53
+ return this.interpolate(translation, { ...params, count });
54
+ }
55
+ /**
56
+ * Get current locale
57
+ */
58
+ getLocale() {
59
+ return this.locale;
60
+ }
61
+ /**
62
+ * Change locale
63
+ */
64
+ async setLocale(locale) {
65
+ // Check if already loading
66
+ if (this.loadingPromises.has(locale)) {
67
+ await this.loadingPromises.get(locale);
68
+ return;
69
+ }
70
+ // Check if already loaded
71
+ if (this.translations.has(locale)) {
72
+ this.applyLocale(locale);
73
+ return;
74
+ }
75
+ // Load translations
76
+ const loadingPromise = this.loadTranslationsForLocale(locale);
77
+ this.loadingPromises.set(locale, loadingPromise);
78
+ try {
79
+ await loadingPromise;
80
+ this.applyLocale(locale);
81
+ }
82
+ finally {
83
+ this.loadingPromises.delete(locale);
84
+ }
85
+ }
86
+ /**
87
+ * Get current direction
88
+ */
89
+ getDirection() {
90
+ return this.direction;
91
+ }
92
+ /**
93
+ * Get available locales
94
+ */
95
+ getAvailableLocales() {
96
+ return Array.from(this.translations.keys());
97
+ }
98
+ /**
99
+ * Check if locale is loaded
100
+ */
101
+ isLocaleLoaded(locale) {
102
+ return this.translations.has(locale);
103
+ }
104
+ /**
105
+ * Subscribe to changes
106
+ */
107
+ subscribe(listener) {
108
+ this.listeners.add(listener);
109
+ return () => {
110
+ this.listeners.delete(listener);
111
+ };
112
+ }
113
+ /**
114
+ * Check if key exists
115
+ */
116
+ hasKey(key) {
117
+ const bundle = this.translations.get(this.locale);
118
+ return !!bundle?.translations[key];
119
+ }
120
+ notifyListeners() {
121
+ for (const listener of this.listeners) {
122
+ listener();
123
+ }
124
+ }
125
+ applyLocale(locale) {
126
+ const bundle = this.translations.get(locale);
127
+ if (!bundle)
128
+ return;
129
+ this.locale = locale;
130
+ this.direction = bundle.direction;
131
+ this.applyDOMDirection();
132
+ this.notifyListeners();
133
+ }
134
+ applyDOMDirection() {
135
+ if (typeof document === "undefined")
136
+ return;
137
+ document.documentElement.setAttribute("dir", this.direction);
138
+ document.documentElement.setAttribute("lang", this.locale);
139
+ }
140
+ async loadTranslationsForLocale(locale) {
141
+ if (!this.config.loadTranslations) {
142
+ throw new Error(`No translation loader configured for locale: ${locale}`);
143
+ }
144
+ const bundle = await this.config.loadTranslations(locale);
145
+ this.translations.set(locale, bundle);
146
+ }
147
+ getTranslation(key) {
148
+ // Try current locale
149
+ const currentBundle = this.translations.get(this.locale);
150
+ if (currentBundle?.translations[key]) {
151
+ return currentBundle.translations[key];
152
+ }
153
+ // Try fallback locale
154
+ const fallbackBundle = this.translations.get(this.fallbackLocale);
155
+ if (fallbackBundle?.translations[key]) {
156
+ return fallbackBundle.translations[key];
157
+ }
158
+ // Missing key
159
+ if (this.config.onMissingKey) {
160
+ this.config.onMissingKey(key, this.locale);
161
+ }
162
+ return key;
163
+ }
164
+ interpolate(text, params) {
165
+ if (!params)
166
+ return text;
167
+ return text.replace(/\{(\w+)\}/g, (match, key) => {
168
+ return params[key]?.toString() || match;
169
+ });
170
+ }
171
+ selectPluralForm(count, locale) {
172
+ // Use Intl.PluralRules if available
173
+ if (typeof Intl !== "undefined" && Intl.PluralRules) {
174
+ try {
175
+ const rules = new Intl.PluralRules(locale);
176
+ const category = rules.select(count);
177
+ return category;
178
+ }
179
+ catch {
180
+ // Fall through to simple rules
181
+ }
182
+ }
183
+ // Fallback to simple rules
184
+ if (count === 0)
185
+ return "zero";
186
+ if (count === 1)
187
+ return "one";
188
+ return "other";
189
+ }
190
+ detectBrowserLocale() {
191
+ if (typeof navigator === "undefined")
192
+ return "en";
193
+ const browserLang = navigator.language ||
194
+ (navigator.languages && navigator.languages[0]) ||
195
+ "en";
196
+ return browserLang.split("-")[0];
197
+ }
198
+ }
199
+ //# sourceMappingURL=simple-i18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple-i18n.js","sourceRoot":"","sources":["../../src/i18n/simple-i18n.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ {
2
+ "common": {
3
+ "save": "حفظ",
4
+ "cancel": "إلغاء",
5
+ "close": "إغلاق",
6
+ "loading": "جار التحميل...",
7
+ "error": "خطأ",
8
+ "retry": "إعادة المحاولة",
9
+ "back": "رجوع",
10
+ "next": "التالي",
11
+ "previous": "السابق",
12
+ "submit": "إرسال",
13
+ "continue": "متابعة",
14
+ "finish": "إنهاء",
15
+ "yes": "نعم",
16
+ "no": "لا",
17
+ "ok": "موافق",
18
+ "settings": "الإعدادات",
19
+ "language": "اللغة",
20
+ "theme": "المظهر",
21
+ "settings_aria": "فتح قائمة الإعدادات",
22
+ "rtl_notice": "اتجاه النص من اليمين إلى اليسار نشط",
23
+ "question": {
24
+ "one": "سؤال",
25
+ "other": "أسئلة"
26
+ },
27
+ "item": {
28
+ "one": "عنصر",
29
+ "other": "عناصر"
30
+ },
31
+ "character": {
32
+ "one": "حرف",
33
+ "other": "حروف"
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "assessment": {
3
+ "title": "التقييم",
4
+ "questions": {
5
+ "one": "{count} سؤال",
6
+ "other": "{count} أسئلة"
7
+ },
8
+ "question_of": "السؤال {current} من {total}",
9
+ "student_name": "اسم الطالب",
10
+ "fullscreen": "ملء الشاشة",
11
+ "exit_fullscreen": "الخروج من ملء الشاشة",
12
+ "enter_fullscreen_aria": "الدخول إلى ملء الشاشة",
13
+ "exit_fullscreen_aria": "الخروج من ملء الشاشة"
14
+ },
15
+ "accommodation": {
16
+ "audio": "صوت",
17
+ "audio_aria": "تبديل الصوت/تحويل النص إلى كلام",
18
+ "contrast": "التباين",
19
+ "contrast_aria": "تبديل تباين الألوان"
20
+ },
21
+ "navigation": {
22
+ "back": "← رجوع",
23
+ "next": "التالي ←",
24
+ "previous": "السابق",
25
+ "submit": "إرسال",
26
+ "navigate_to": "الانتقال إلى السؤال {index}",
27
+ "section": "القسم"
28
+ },
29
+ "section": {
30
+ "title": "بنية التقييم",
31
+ "add": "+ إضافة قسم",
32
+ "untitled": "قسم بدون عنوان",
33
+ "remove": "حذف القسم",
34
+ "items": {
35
+ "one": "{count} عنصر",
36
+ "other": "{count} عناصر"
37
+ },
38
+ "aria_label": "القسم: {title}",
39
+ "drop_zone": "إسقاط العناصر هنا",
40
+ "unassigned": "عناصر غير مخصصة",
41
+ "unassigned_instruction": "اسحب هذه العناصر إلى الأقسام",
42
+ "unassigned_item_aria": "سؤال غير مخصص: {title}"
43
+ },
44
+ "item": {
45
+ "load_error": "تعذر تحميل السؤال.",
46
+ "untitled": "بدون عنوان"
47
+ }
48
+ }