@secorto/i18n 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Represents a localized entry in the translation system.
3
+ * @template E - The type of the content (e.g., { title: string, body: string }).
4
+ * @template C - The section of the application (e.g., 'blog', 'docs').
5
+ * @template L - The language code (e.g., 'es', 'en').
6
+ */
7
+ export interface LocalizedEntry<
8
+ TEntry,
9
+ L extends string
10
+ > {
11
+ cleanId: string
12
+ translationKey: string
13
+ locale: L
14
+ draft: boolean
15
+ original: TEntry
16
+ }
17
+
18
+ /**
19
+ * Represents a translation index that groups localized entries by their translation key and locale.
20
+ * @template L - The type of the language code (e.g., 'es', 'en').
21
+ * @template E - The type of the content (e.g., { title: string, body: string }).
22
+ * @template C - The section of the application (e.g., 'blog', 'docs').
23
+ */
24
+ export type TranslationIndex<
25
+ L extends string,
26
+ TEntry
27
+ > = Record<
28
+ string,
29
+ Partial<Record<L, LocalizedEntry<TEntry, L>>>
30
+ >
31
+
32
+ /**
33
+ * Builds a translation index from an array of localized entries.
34
+ * The index groups entries by their translation key and locale.
35
+ * If duplicate entries for the same translation key and locale are found, an error is thrown.
36
+ * @template E - The type of the content (e.g., { title: string, body: string }).
37
+ * @template C - The section of the application (e.g., 'blog', 'docs').
38
+ * @template L - The language code (e.g., 'es', 'en').
39
+ * @param entries Entries to index
40
+ * @returns The translation index, grouped by translation key and locale
41
+ * @throws Error if duplicate entries for the same translation key and locale are found
42
+ */
43
+ export function createTranslationIndex<
44
+ L extends string,
45
+ TEntry
46
+ >(
47
+ entries: readonly LocalizedEntry<TEntry, L>[]
48
+ ): TranslationIndex<L, TEntry> {
49
+ // Using map to safely mutate internally without lying to TypeScript
50
+ const map = new Map<string, Partial<Record<L, LocalizedEntry<TEntry, L>>>>()
51
+
52
+ for (const entry of entries) {
53
+ const key = entry.translationKey
54
+ const locale = entry.locale
55
+
56
+ // Get or create the group for this key
57
+ let group = map.get(key)
58
+ if (!group) {
59
+ group = {}
60
+ map.set(key, group)
61
+ } else if (locale in group) {
62
+ throw new Error(
63
+ `Duplicate translation for key "${key}" and locale "${locale}"`
64
+ )
65
+ }
66
+
67
+ // Assign directly to the entry
68
+ group[locale] = entry
69
+ }
70
+ return Object.fromEntries(map)
71
+ }