@kanso-protocol/i18n 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,166 @@
1
+ import { InjectionToken, inject } from '@angular/core';
2
+
3
+ /**
4
+ * BCP-47 locale tag used by every Kanso component that calls into Intl
5
+ * APIs (date / time / number formatting, weekday names, etc.).
6
+ *
7
+ * Default factory pulls from `navigator.language` if available, else
8
+ * falls back to `'en-US'`. Override at the app root:
9
+ *
10
+ * providers: [{ provide: KP_LOCALE, useValue: 'fr-FR' }]
11
+ *
12
+ * Or per-feature via a child injector. Components inject this lazily —
13
+ * changing it at runtime requires re-rendering the affected components.
14
+ */
15
+ const KP_LOCALE = new InjectionToken('KP_LOCALE', {
16
+ factory: () => typeof navigator !== 'undefined' && navigator.language
17
+ ? navigator.language
18
+ : 'en-US',
19
+ });
20
+ /**
21
+ * Built-in English strings. Components that read these go through
22
+ * `injectKpStrings()` so consumers can override per-app or per-locale.
23
+ */
24
+ const KP_DEFAULT_STRINGS_EN = {
25
+ close: 'Close',
26
+ clear: 'Clear',
27
+ cancel: 'Cancel',
28
+ confirm: 'Confirm',
29
+ loading: 'Loading…',
30
+ noResults: 'No results found',
31
+ today: 'Today',
32
+ yesterday: 'Yesterday',
33
+ thisWeek: 'This week',
34
+ lastWeek: 'Last week',
35
+ thisMonth: 'This month',
36
+ lastMonth: 'Last month',
37
+ selectDate: 'Select date',
38
+ selectTime: 'Select time',
39
+ previousMonth: 'Previous month',
40
+ nextMonth: 'Next month',
41
+ dropzoneTitle: 'Drop files here or click to browse',
42
+ dropzoneRemove: (filename) => `Remove ${filename}`,
43
+ dropzoneUploaded: 'Uploaded',
44
+ searchPlaceholder: 'Search…',
45
+ commandPaletteHint: '⌘K',
46
+ commandPalettePlaceholder: 'Type a command or search…',
47
+ };
48
+ /**
49
+ * App-level override token. Provide a `Partial<KpLocaleStrings>` —
50
+ * unspecified keys fall through to the English defaults.
51
+ *
52
+ * providers: [{
53
+ * provide: KP_STRINGS,
54
+ * useValue: {
55
+ * close: 'Закрыть',
56
+ * today: 'Сегодня',
57
+ * commandPalettePlaceholder: 'Команда или поиск…',
58
+ * },
59
+ * }]
60
+ */
61
+ const KP_STRINGS = new InjectionToken('KP_STRINGS', { factory: () => ({}) });
62
+ /**
63
+ * Resolve the merged strings dictionary inside a component / directive
64
+ * factory. Reads both the override token and the defaults; consumers
65
+ * never have to remember to merge.
66
+ */
67
+ function injectKpStrings() {
68
+ const overrides = inject(KP_STRINGS);
69
+ return { ...KP_DEFAULT_STRINGS_EN, ...overrides };
70
+ }
71
+ /** Convenience accessor with the same lifecycle constraints as `inject(KP_LOCALE)`. */
72
+ function injectKpLocale() {
73
+ return inject(KP_LOCALE);
74
+ }
75
+
76
+ /**
77
+ * Thin wrappers over `Intl.DateTimeFormat` so components that take
78
+ * `KP_LOCALE` don't have to repeat the `new Intl.DateTimeFormat(...)`
79
+ * dance. Each helper caches the formatter per (locale, options) — the
80
+ * cache is keyed on a JSON-stringified options object since `Intl`
81
+ * options are small and structurally compared.
82
+ */
83
+ const CACHE = new Map();
84
+ function getFormatter(locale, options) {
85
+ const key = `${locale}::${JSON.stringify(options)}`;
86
+ let f = CACHE.get(key);
87
+ if (!f) {
88
+ f = new Intl.DateTimeFormat(locale, options);
89
+ CACHE.set(key, f);
90
+ }
91
+ return f;
92
+ }
93
+ /**
94
+ * Format a date in the consumer's locale.
95
+ *
96
+ * kpFormatDate(d, 'fr-FR', { dateStyle: 'medium' }) // "5 mai 2026"
97
+ */
98
+ function kpFormatDate(date, locale, options = { dateStyle: 'medium' }) {
99
+ return getFormatter(locale, options).format(date);
100
+ }
101
+ /**
102
+ * Format the time portion of a date.
103
+ *
104
+ * kpFormatTime(d, 'en-US', { hour: 'numeric', minute: '2-digit' }) // "3:45 PM"
105
+ * kpFormatTime(d, 'de-DE') // "15:45"
106
+ */
107
+ function kpFormatTime(date, locale, options = { timeStyle: 'short' }) {
108
+ return getFormatter(locale, options).format(date);
109
+ }
110
+ /**
111
+ * Localized month names. Reuses a single formatter; the calendar
112
+ * components walk all 12 months once on render.
113
+ *
114
+ * kpMonthNames('en-US', 'long') // ['January', 'February', ...]
115
+ * kpMonthNames('ru-RU', 'short') // ['янв.', 'февр.', ...]
116
+ */
117
+ function kpMonthNames(locale, format = 'long') {
118
+ const fmt = getFormatter(locale, { month: format });
119
+ const out = [];
120
+ // Use day=1 of each month at year=2000 (safe — no month has fewer than 1 day,
121
+ // year is well after epoch + DST offsets don't shift the month).
122
+ for (let m = 0; m < 12; m++)
123
+ out.push(fmt.format(new Date(2000, m, 1)));
124
+ return out;
125
+ }
126
+ /**
127
+ * Localized weekday short labels in display order, starting from
128
+ * `firstDayOfWeek` (0 = Sunday, 1 = Monday).
129
+ *
130
+ * kpWeekdayNames('en-US', 1, 'narrow') // ['M', 'T', 'W', 'T', 'F', 'S', 'S']
131
+ * kpWeekdayNames('en-US', 1, 'short') // ['Mon', 'Tue', ...]
132
+ */
133
+ function kpWeekdayNames(locale, firstDayOfWeek = 1, format = 'short') {
134
+ const fmt = getFormatter(locale, { weekday: format });
135
+ // Pick a reference week starting on Sunday 2017-01-01 (Sunday = 0).
136
+ const out = [];
137
+ for (let i = 0; i < 7; i++) {
138
+ const d = new Date(2017, 0, 1 + i);
139
+ out.push(fmt.format(d));
140
+ }
141
+ if (firstDayOfWeek === 1) {
142
+ return [...out.slice(1), out[0]];
143
+ }
144
+ return out;
145
+ }
146
+ /**
147
+ * AM/PM marker for a given hour in the consumer's locale, or empty
148
+ * string if the locale uses 24h format (most of the world).
149
+ *
150
+ * kpDayPeriod(15, 'en-US') // 'PM'
151
+ * kpDayPeriod(15, 'de-DE') // ''
152
+ */
153
+ function kpDayPeriod(hour, locale) {
154
+ const fmt = getFormatter(locale, { hour: 'numeric', hour12: true });
155
+ // Format "3 PM" → match trailing letters
156
+ const formatted = fmt.format(new Date(2000, 0, 1, hour));
157
+ const m = formatted.match(/[A-Za-zА-Яа-я]+\.?$/);
158
+ return m ? m[0] : '';
159
+ }
160
+
161
+ /**
162
+ * Generated bundle index. Do not edit.
163
+ */
164
+
165
+ export { KP_DEFAULT_STRINGS_EN, KP_LOCALE, KP_STRINGS, injectKpLocale, injectKpStrings, kpDayPeriod, kpFormatDate, kpFormatTime, kpMonthNames, kpWeekdayNames };
166
+ //# sourceMappingURL=kanso-protocol-i18n.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kanso-protocol-i18n.mjs","sources":["../../../../packages/i18n/src/tokens.ts","../../../../packages/i18n/src/intl.ts","../../../../packages/i18n/src/kanso-protocol-i18n.ts"],"sourcesContent":["import { InjectionToken, inject } from '@angular/core';\n\n/**\n * BCP-47 locale tag used by every Kanso component that calls into Intl\n * APIs (date / time / number formatting, weekday names, etc.).\n *\n * Default factory pulls from `navigator.language` if available, else\n * falls back to `'en-US'`. Override at the app root:\n *\n * providers: [{ provide: KP_LOCALE, useValue: 'fr-FR' }]\n *\n * Or per-feature via a child injector. Components inject this lazily —\n * changing it at runtime requires re-rendering the affected components.\n */\nexport const KP_LOCALE = new InjectionToken<string>('KP_LOCALE', {\n factory: () =>\n typeof navigator !== 'undefined' && navigator.language\n ? navigator.language\n : 'en-US',\n});\n\n/**\n * Static UI strings that don't have an Intl equivalent — labels, ARIA\n * fallbacks, button text. Anything that DOES have an Intl form (month\n * names, day-period markers, time formats) is derived from `KP_LOCALE`\n * via the helpers in `intl.ts` instead of being listed here.\n *\n * Add a key here only after you've confirmed it's not derivable from\n * Intl. The goal is a small registry — large registries rot fast.\n */\nexport interface KpLocaleStrings {\n // Generic chrome\n close: string;\n clear: string;\n cancel: string;\n confirm: string;\n loading: string;\n noResults: string;\n\n // Date / time pickers — buttons + presets\n today: string;\n yesterday: string;\n thisWeek: string;\n lastWeek: string;\n thisMonth: string;\n lastMonth: string;\n selectDate: string;\n selectTime: string;\n previousMonth: string;\n nextMonth: string;\n\n // File upload\n dropzoneTitle: string;\n dropzoneRemove: (filename: string) => string;\n dropzoneUploaded: string;\n\n // Search / command palette\n searchPlaceholder: string;\n commandPaletteHint: string;\n commandPalettePlaceholder: string;\n}\n\n/**\n * Built-in English strings. Components that read these go through\n * `injectKpStrings()` so consumers can override per-app or per-locale.\n */\nexport const KP_DEFAULT_STRINGS_EN: KpLocaleStrings = {\n close: 'Close',\n clear: 'Clear',\n cancel: 'Cancel',\n confirm: 'Confirm',\n loading: 'Loading…',\n noResults: 'No results found',\n\n today: 'Today',\n yesterday: 'Yesterday',\n thisWeek: 'This week',\n lastWeek: 'Last week',\n thisMonth: 'This month',\n lastMonth: 'Last month',\n selectDate: 'Select date',\n selectTime: 'Select time',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n\n dropzoneTitle: 'Drop files here or click to browse',\n dropzoneRemove: (filename) => `Remove ${filename}`,\n dropzoneUploaded: 'Uploaded',\n\n searchPlaceholder: 'Search…',\n commandPaletteHint: '⌘K',\n commandPalettePlaceholder: 'Type a command or search…',\n};\n\n/**\n * App-level override token. Provide a `Partial<KpLocaleStrings>` —\n * unspecified keys fall through to the English defaults.\n *\n * providers: [{\n * provide: KP_STRINGS,\n * useValue: {\n * close: 'Закрыть',\n * today: 'Сегодня',\n * commandPalettePlaceholder: 'Команда или поиск…',\n * },\n * }]\n */\nexport const KP_STRINGS = new InjectionToken<Partial<KpLocaleStrings>>(\n 'KP_STRINGS',\n { factory: () => ({}) },\n);\n\n/**\n * Resolve the merged strings dictionary inside a component / directive\n * factory. Reads both the override token and the defaults; consumers\n * never have to remember to merge.\n */\nexport function injectKpStrings(): KpLocaleStrings {\n const overrides = inject(KP_STRINGS);\n return { ...KP_DEFAULT_STRINGS_EN, ...overrides };\n}\n\n/** Convenience accessor with the same lifecycle constraints as `inject(KP_LOCALE)`. */\nexport function injectKpLocale(): string {\n return inject(KP_LOCALE);\n}\n","/**\n * Thin wrappers over `Intl.DateTimeFormat` so components that take\n * `KP_LOCALE` don't have to repeat the `new Intl.DateTimeFormat(...)`\n * dance. Each helper caches the formatter per (locale, options) — the\n * cache is keyed on a JSON-stringified options object since `Intl`\n * options are small and structurally compared.\n */\n\nconst CACHE = new Map<string, Intl.DateTimeFormat>();\n\nfunction getFormatter(locale: string, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {\n const key = `${locale}::${JSON.stringify(options)}`;\n let f = CACHE.get(key);\n if (!f) {\n f = new Intl.DateTimeFormat(locale, options);\n CACHE.set(key, f);\n }\n return f;\n}\n\n/**\n * Format a date in the consumer's locale.\n *\n * kpFormatDate(d, 'fr-FR', { dateStyle: 'medium' }) // \"5 mai 2026\"\n */\nexport function kpFormatDate(\n date: Date,\n locale: string,\n options: Intl.DateTimeFormatOptions = { dateStyle: 'medium' },\n): string {\n return getFormatter(locale, options).format(date);\n}\n\n/**\n * Format the time portion of a date.\n *\n * kpFormatTime(d, 'en-US', { hour: 'numeric', minute: '2-digit' }) // \"3:45 PM\"\n * kpFormatTime(d, 'de-DE') // \"15:45\"\n */\nexport function kpFormatTime(\n date: Date,\n locale: string,\n options: Intl.DateTimeFormatOptions = { timeStyle: 'short' },\n): string {\n return getFormatter(locale, options).format(date);\n}\n\n/**\n * Localized month names. Reuses a single formatter; the calendar\n * components walk all 12 months once on render.\n *\n * kpMonthNames('en-US', 'long') // ['January', 'February', ...]\n * kpMonthNames('ru-RU', 'short') // ['янв.', 'февр.', ...]\n */\nexport function kpMonthNames(\n locale: string,\n format: 'long' | 'short' | 'narrow' = 'long',\n): string[] {\n const fmt = getFormatter(locale, { month: format });\n const out: string[] = [];\n // Use day=1 of each month at year=2000 (safe — no month has fewer than 1 day,\n // year is well after epoch + DST offsets don't shift the month).\n for (let m = 0; m < 12; m++) out.push(fmt.format(new Date(2000, m, 1)));\n return out;\n}\n\n/**\n * Localized weekday short labels in display order, starting from\n * `firstDayOfWeek` (0 = Sunday, 1 = Monday).\n *\n * kpWeekdayNames('en-US', 1, 'narrow') // ['M', 'T', 'W', 'T', 'F', 'S', 'S']\n * kpWeekdayNames('en-US', 1, 'short') // ['Mon', 'Tue', ...]\n */\nexport function kpWeekdayNames(\n locale: string,\n firstDayOfWeek: 0 | 1 = 1,\n format: 'long' | 'short' | 'narrow' = 'short',\n): string[] {\n const fmt = getFormatter(locale, { weekday: format });\n // Pick a reference week starting on Sunday 2017-01-01 (Sunday = 0).\n const out: string[] = [];\n for (let i = 0; i < 7; i++) {\n const d = new Date(2017, 0, 1 + i);\n out.push(fmt.format(d));\n }\n if (firstDayOfWeek === 1) {\n return [...out.slice(1), out[0]];\n }\n return out;\n}\n\n/**\n * AM/PM marker for a given hour in the consumer's locale, or empty\n * string if the locale uses 24h format (most of the world).\n *\n * kpDayPeriod(15, 'en-US') // 'PM'\n * kpDayPeriod(15, 'de-DE') // ''\n */\nexport function kpDayPeriod(hour: number, locale: string): string {\n const fmt = getFormatter(locale, { hour: 'numeric', hour12: true });\n // Format \"3 PM\" → match trailing letters\n const formatted = fmt.format(new Date(2000, 0, 1, hour));\n const m = formatted.match(/[A-Za-zА-Яа-я]+\\.?$/);\n return m ? m[0] : '';\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@kanso-protocol/i18n",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "peerDependencies": {
6
+ "@angular/core": "^18.0.0"
7
+ },
8
+ "description": "Kanso Protocol — i18n primitives (locale token + string registry + Intl helpers).",
9
+ "author": "GregNBlack",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/GregNBlack/kanso-protocol.git",
13
+ "directory": "packages/i18n"
14
+ },
15
+ "homepage": "https://gregnblack.github.io/kanso-protocol",
16
+ "bugs": "https://github.com/GregNBlack/kanso-protocol/issues",
17
+ "keywords": [
18
+ "design-system",
19
+ "angular",
20
+ "kanso",
21
+ "i18n",
22
+ "localization"
23
+ ],
24
+ "sideEffects": false,
25
+ "module": "fesm2022/kanso-protocol-i18n.mjs",
26
+ "typings": "types/kanso-protocol-i18n.d.ts",
27
+ "exports": {
28
+ "./package.json": {
29
+ "default": "./package.json"
30
+ },
31
+ ".": {
32
+ "types": "./types/kanso-protocol-i18n.d.ts",
33
+ "default": "./fesm2022/kanso-protocol-i18n.mjs"
34
+ }
35
+ },
36
+ "type": "module",
37
+ "dependencies": {
38
+ "tslib": "^2.3.0"
39
+ }
40
+ }
@@ -0,0 +1,123 @@
1
+ import { InjectionToken } from '@angular/core';
2
+
3
+ /**
4
+ * BCP-47 locale tag used by every Kanso component that calls into Intl
5
+ * APIs (date / time / number formatting, weekday names, etc.).
6
+ *
7
+ * Default factory pulls from `navigator.language` if available, else
8
+ * falls back to `'en-US'`. Override at the app root:
9
+ *
10
+ * providers: [{ provide: KP_LOCALE, useValue: 'fr-FR' }]
11
+ *
12
+ * Or per-feature via a child injector. Components inject this lazily —
13
+ * changing it at runtime requires re-rendering the affected components.
14
+ */
15
+ declare const KP_LOCALE: InjectionToken<string>;
16
+ /**
17
+ * Static UI strings that don't have an Intl equivalent — labels, ARIA
18
+ * fallbacks, button text. Anything that DOES have an Intl form (month
19
+ * names, day-period markers, time formats) is derived from `KP_LOCALE`
20
+ * via the helpers in `intl.ts` instead of being listed here.
21
+ *
22
+ * Add a key here only after you've confirmed it's not derivable from
23
+ * Intl. The goal is a small registry — large registries rot fast.
24
+ */
25
+ interface KpLocaleStrings {
26
+ close: string;
27
+ clear: string;
28
+ cancel: string;
29
+ confirm: string;
30
+ loading: string;
31
+ noResults: string;
32
+ today: string;
33
+ yesterday: string;
34
+ thisWeek: string;
35
+ lastWeek: string;
36
+ thisMonth: string;
37
+ lastMonth: string;
38
+ selectDate: string;
39
+ selectTime: string;
40
+ previousMonth: string;
41
+ nextMonth: string;
42
+ dropzoneTitle: string;
43
+ dropzoneRemove: (filename: string) => string;
44
+ dropzoneUploaded: string;
45
+ searchPlaceholder: string;
46
+ commandPaletteHint: string;
47
+ commandPalettePlaceholder: string;
48
+ }
49
+ /**
50
+ * Built-in English strings. Components that read these go through
51
+ * `injectKpStrings()` so consumers can override per-app or per-locale.
52
+ */
53
+ declare const KP_DEFAULT_STRINGS_EN: KpLocaleStrings;
54
+ /**
55
+ * App-level override token. Provide a `Partial<KpLocaleStrings>` —
56
+ * unspecified keys fall through to the English defaults.
57
+ *
58
+ * providers: [{
59
+ * provide: KP_STRINGS,
60
+ * useValue: {
61
+ * close: 'Закрыть',
62
+ * today: 'Сегодня',
63
+ * commandPalettePlaceholder: 'Команда или поиск…',
64
+ * },
65
+ * }]
66
+ */
67
+ declare const KP_STRINGS: InjectionToken<Partial<KpLocaleStrings>>;
68
+ /**
69
+ * Resolve the merged strings dictionary inside a component / directive
70
+ * factory. Reads both the override token and the defaults; consumers
71
+ * never have to remember to merge.
72
+ */
73
+ declare function injectKpStrings(): KpLocaleStrings;
74
+ /** Convenience accessor with the same lifecycle constraints as `inject(KP_LOCALE)`. */
75
+ declare function injectKpLocale(): string;
76
+
77
+ /**
78
+ * Thin wrappers over `Intl.DateTimeFormat` so components that take
79
+ * `KP_LOCALE` don't have to repeat the `new Intl.DateTimeFormat(...)`
80
+ * dance. Each helper caches the formatter per (locale, options) — the
81
+ * cache is keyed on a JSON-stringified options object since `Intl`
82
+ * options are small and structurally compared.
83
+ */
84
+ /**
85
+ * Format a date in the consumer's locale.
86
+ *
87
+ * kpFormatDate(d, 'fr-FR', { dateStyle: 'medium' }) // "5 mai 2026"
88
+ */
89
+ declare function kpFormatDate(date: Date, locale: string, options?: Intl.DateTimeFormatOptions): string;
90
+ /**
91
+ * Format the time portion of a date.
92
+ *
93
+ * kpFormatTime(d, 'en-US', { hour: 'numeric', minute: '2-digit' }) // "3:45 PM"
94
+ * kpFormatTime(d, 'de-DE') // "15:45"
95
+ */
96
+ declare function kpFormatTime(date: Date, locale: string, options?: Intl.DateTimeFormatOptions): string;
97
+ /**
98
+ * Localized month names. Reuses a single formatter; the calendar
99
+ * components walk all 12 months once on render.
100
+ *
101
+ * kpMonthNames('en-US', 'long') // ['January', 'February', ...]
102
+ * kpMonthNames('ru-RU', 'short') // ['янв.', 'февр.', ...]
103
+ */
104
+ declare function kpMonthNames(locale: string, format?: 'long' | 'short' | 'narrow'): string[];
105
+ /**
106
+ * Localized weekday short labels in display order, starting from
107
+ * `firstDayOfWeek` (0 = Sunday, 1 = Monday).
108
+ *
109
+ * kpWeekdayNames('en-US', 1, 'narrow') // ['M', 'T', 'W', 'T', 'F', 'S', 'S']
110
+ * kpWeekdayNames('en-US', 1, 'short') // ['Mon', 'Tue', ...]
111
+ */
112
+ declare function kpWeekdayNames(locale: string, firstDayOfWeek?: 0 | 1, format?: 'long' | 'short' | 'narrow'): string[];
113
+ /**
114
+ * AM/PM marker for a given hour in the consumer's locale, or empty
115
+ * string if the locale uses 24h format (most of the world).
116
+ *
117
+ * kpDayPeriod(15, 'en-US') // 'PM'
118
+ * kpDayPeriod(15, 'de-DE') // ''
119
+ */
120
+ declare function kpDayPeriod(hour: number, locale: string): string;
121
+
122
+ export { KP_DEFAULT_STRINGS_EN, KP_LOCALE, KP_STRINGS, injectKpLocale, injectKpStrings, kpDayPeriod, kpFormatDate, kpFormatTime, kpMonthNames, kpWeekdayNames };
123
+ export type { KpLocaleStrings };