wacom 21.1.24 → 21.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.
- package/README.md +292 -210
- package/fesm2022/wacom.mjs +1786 -1567
- package/fesm2022/wacom.mjs.map +1 -1
- package/package.json +34 -89
- package/types/wacom.d.ts +1162 -1040
package/README.md
CHANGED
|
@@ -54,6 +54,7 @@ export const appConfig = {
|
|
|
54
54
|
| Name | Description |
|
|
55
55
|
| -------------------------------------------------------------------- | :-----------------------------------------------------------------: |
|
|
56
56
|
| [**`Core`**](https://www.npmjs.com/package/wacom#core-service) | Common supportive function which can be used in any service |
|
|
57
|
+
| [**`Emitter`**](#emitter-service) | Lightweight app-wide event and task signaling |
|
|
57
58
|
| [**`Http`**](https://www.npmjs.com/package/wacom#http-service) | Http layer for HttpClient |
|
|
58
59
|
| [**`Store`**](https://www.npmjs.com/package/wacom#store-service) | Service responsible for keeping information on the device |
|
|
59
60
|
| [**`Meta`**](https://www.npmjs.com/package/wacom#meta-service) | Website meta tags management within router |
|
|
@@ -65,65 +66,7 @@ export const appConfig = {
|
|
|
65
66
|
| [**`RTC`**](https://www.npmjs.com/package/wacom#rtc-service) | Wraps WebRTC peer connections and local media streams |
|
|
66
67
|
| [**`Util`**](https://www.npmjs.com/package/wacom#util-service) | Utility methods for forms, validation, and CSS variables |
|
|
67
68
|
| [**`Theme`**](#theme-service) | Manages UI theme mode, density, and radius preferences |
|
|
68
|
-
| [**`
|
|
69
|
-
|
|
70
|
-
## [Emitter Service](#emitter-service)
|
|
71
|
-
|
|
72
|
-
The `EmitterService` provides a lightweight event bus and completion signaling built on Angular Signals and RxJS.
|
|
73
|
-
|
|
74
|
-
### Events
|
|
75
|
-
|
|
76
|
-
- `emit(id: string, data?: any): void`: Publish an event on a channel.
|
|
77
|
-
- `on<T = any>(id: string): Observable<T>`: Subscribe to a channel (hot, no replay).
|
|
78
|
-
- `off(id: string): void`: Close and remove a channel.
|
|
79
|
-
- `offAll(): void`: Close and remove all channels.
|
|
80
|
-
- `has(id: string): boolean`: Check if a channel exists.
|
|
81
|
-
|
|
82
|
-
Example:
|
|
83
|
-
|
|
84
|
-
```ts
|
|
85
|
-
import { EmitterService } from 'wacom';
|
|
86
|
-
|
|
87
|
-
constructor(private emitter: EmitterService) {}
|
|
88
|
-
|
|
89
|
-
ngOnInit() {
|
|
90
|
-
this.emitter.on<string>('user:login').subscribe((uid) => {
|
|
91
|
-
console.log('Logged in:', uid);
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
login(uid: string) {
|
|
96
|
-
this.emitter.emit('user:login', uid);
|
|
97
|
-
}
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### Completion tasks
|
|
101
|
-
|
|
102
|
-
Track once-off tasks and await their completion.
|
|
103
|
-
|
|
104
|
-
- `complete<T = any>(task: string, value: T = true): void`: Mark task done with payload.
|
|
105
|
-
- `clearCompleted(task: string): void`: Reset completion state.
|
|
106
|
-
- `completed(task: string): any | undefined`: Read current payload or `undefined`.
|
|
107
|
-
- `isCompleted(task: string): boolean`: Convenience check.
|
|
108
|
-
- `onComplete(tasks: string | string[], opts?: { mode?: 'all' | 'any'; timeoutMs?: number; abort?: AbortSignal; }): Observable<any | any[]>`: Await task(s) completion.
|
|
109
|
-
|
|
110
|
-
Example:
|
|
111
|
-
|
|
112
|
-
```ts
|
|
113
|
-
// Somewhere that waits for a single task
|
|
114
|
-
this.emitter.onComplete("profile:loaded").subscribe(() => {
|
|
115
|
-
// safe to render UI
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Somewhere that fulfills it
|
|
119
|
-
await api.loadProfile();
|
|
120
|
-
this.emitter.complete("profile:loaded");
|
|
121
|
-
|
|
122
|
-
// Wait for any of several tasks
|
|
123
|
-
this.emitter
|
|
124
|
-
.onComplete(["a", "b"], { mode: "any", timeoutMs: 5000 })
|
|
125
|
-
.subscribe((which) => console.log("First done:", which));
|
|
126
|
-
```
|
|
69
|
+
| [**`Translation`**](#translation-service) | Lightweight, signal-based runtime translation engine |
|
|
127
70
|
|
|
128
71
|
## [Core Service](#core-service)
|
|
129
72
|
|
|
@@ -503,6 +446,64 @@ In this example:
|
|
|
503
446
|
|
|
504
447
|
This ensures controlled access to the resource, preventing race conditions and ensuring data integrity.
|
|
505
448
|
|
|
449
|
+
## [Emitter Service](#emitter-service)
|
|
450
|
+
|
|
451
|
+
The `EmitterService` provides a lightweight event bus and completion signaling built on Angular Signals and RxJS.
|
|
452
|
+
|
|
453
|
+
### Events
|
|
454
|
+
|
|
455
|
+
- `emit(id: string, data?: any): void`: Publish an event on a channel.
|
|
456
|
+
- `on<T = any>(id: string): Observable<T>`: Subscribe to a channel (hot, no replay).
|
|
457
|
+
- `off(id: string): void`: Close and remove a channel.
|
|
458
|
+
- `offAll(): void`: Close and remove all channels.
|
|
459
|
+
- `has(id: string): boolean`: Check if a channel exists.
|
|
460
|
+
|
|
461
|
+
Example:
|
|
462
|
+
|
|
463
|
+
```ts
|
|
464
|
+
import { EmitterService } from 'wacom';
|
|
465
|
+
|
|
466
|
+
constructor(private emitter: EmitterService) {}
|
|
467
|
+
|
|
468
|
+
ngOnInit() {
|
|
469
|
+
this.emitter.on<string>('user:login').subscribe((uid) => {
|
|
470
|
+
console.log('Logged in:', uid);
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
login(uid: string) {
|
|
475
|
+
this.emitter.emit('user:login', uid);
|
|
476
|
+
}
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Completion tasks
|
|
480
|
+
|
|
481
|
+
Track once-off tasks and await their completion.
|
|
482
|
+
|
|
483
|
+
- `complete<T = any>(task: string, value: T = true): void`: Mark task done with payload.
|
|
484
|
+
- `clearCompleted(task: string): void`: Reset completion state.
|
|
485
|
+
- `completed(task: string): any | undefined`: Read current payload or `undefined`.
|
|
486
|
+
- `isCompleted(task: string): boolean`: Convenience check.
|
|
487
|
+
- `onComplete(tasks: string | string[], opts?: { mode?: 'all' | 'any'; timeoutMs?: number; abort?: AbortSignal; }): Observable<any | any[]>`: Await task(s) completion.
|
|
488
|
+
|
|
489
|
+
Example:
|
|
490
|
+
|
|
491
|
+
```ts
|
|
492
|
+
// Somewhere that waits for a single task
|
|
493
|
+
this.emitter.onComplete("profile:loaded").subscribe(() => {
|
|
494
|
+
// safe to render UI
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
// Somewhere that fulfills it
|
|
498
|
+
await api.loadProfile();
|
|
499
|
+
this.emitter.complete("profile:loaded");
|
|
500
|
+
|
|
501
|
+
// Wait for any of several tasks
|
|
502
|
+
this.emitter
|
|
503
|
+
.onComplete(["a", "b"], { mode: "any", timeoutMs: 5000 })
|
|
504
|
+
.subscribe((which) => console.log("First done:", which));
|
|
505
|
+
```
|
|
506
|
+
|
|
506
507
|
## [Http Service](#http-service)
|
|
507
508
|
|
|
508
509
|
The `HttpService` provides an HTTP layer for `HttpClient` in Angular, supporting both callbacks and observables for various HTTP operations.
|
|
@@ -712,224 +713,179 @@ httpService.unlock();
|
|
|
712
713
|
|
|
713
714
|
## [Store Service](#store-service)
|
|
714
715
|
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
### Properties
|
|
718
|
-
|
|
719
|
-
#### `_prefix: string`
|
|
720
|
-
|
|
721
|
-
The prefix for storage keys.
|
|
716
|
+
`StoreService` provides a unified, async-first API for working with storage (localStorage by default or a custom provider via config).
|
|
717
|
+
It supports raw values, safe JSON handling, key prefixing, and optional lifecycle hooks.
|
|
722
718
|
|
|
723
|
-
|
|
719
|
+
---
|
|
724
720
|
|
|
725
|
-
|
|
721
|
+
### Key features
|
|
726
722
|
|
|
727
|
-
|
|
728
|
-
|
|
723
|
+
- async/await everywhere (no separate `*Async` methods)
|
|
724
|
+
- optional side-effects via `options`
|
|
725
|
+
- automatic JSON corruption handling
|
|
726
|
+
- configurable storage backend
|
|
727
|
+
- prefix support for namespacing
|
|
729
728
|
|
|
730
|
-
|
|
729
|
+
---
|
|
731
730
|
|
|
732
|
-
|
|
731
|
+
### Prefixing keys
|
|
733
732
|
|
|
734
|
-
```
|
|
735
|
-
storeService.setPrefix(
|
|
733
|
+
```ts
|
|
734
|
+
storeService.setPrefix("app_");
|
|
736
735
|
```
|
|
737
736
|
|
|
738
|
-
|
|
737
|
+
All keys will be stored as `app_<key>` (plus global config prefix if defined).
|
|
739
738
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
**Parameters**:
|
|
739
|
+
---
|
|
743
740
|
|
|
744
|
-
|
|
745
|
-
- `value` (string): The value to store.
|
|
746
|
-
- `callback` (function): The callback to execute on success.
|
|
747
|
-
- `errCallback` (function): The callback to execute on error.
|
|
741
|
+
### set
|
|
748
742
|
|
|
749
|
-
|
|
743
|
+
Stores a raw string value.
|
|
750
744
|
|
|
751
|
-
```
|
|
752
|
-
storeService.set(
|
|
745
|
+
```ts
|
|
746
|
+
await storeService.set("token", "abc123");
|
|
753
747
|
```
|
|
754
748
|
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
Sets a value in storage asynchronously.
|
|
758
|
-
|
|
759
|
-
**Parameters**:
|
|
760
|
-
|
|
761
|
-
- `key` (string): The storage key.
|
|
762
|
-
- `value` (string): The value to store.
|
|
763
|
-
|
|
764
|
-
**Returns**:
|
|
765
|
-
|
|
766
|
-
- `Promise<boolean>`: A promise that resolves to a boolean indicating success.
|
|
749
|
+
With hooks:
|
|
767
750
|
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
751
|
+
```ts
|
|
752
|
+
await storeService.set("token", "abc123", {
|
|
753
|
+
onSuccess: () => console.log("saved"),
|
|
754
|
+
onError: console.error,
|
|
755
|
+
});
|
|
772
756
|
```
|
|
773
757
|
|
|
774
|
-
|
|
758
|
+
**Returns:** `Promise<boolean>`
|
|
775
759
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
**Parameters**:
|
|
760
|
+
---
|
|
779
761
|
|
|
780
|
-
|
|
781
|
-
- `callback` (function): The callback to execute with the retrieved value.
|
|
782
|
-
- `errCallback` (function): The callback to execute on error.
|
|
762
|
+
### get
|
|
783
763
|
|
|
784
|
-
|
|
764
|
+
Retrieves a raw string value.
|
|
785
765
|
|
|
786
|
-
```
|
|
787
|
-
|
|
766
|
+
```ts
|
|
767
|
+
const token = await storeService.get("token");
|
|
788
768
|
```
|
|
789
769
|
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
Gets a value from storage asynchronously.
|
|
793
|
-
|
|
794
|
-
**Parameters**:
|
|
795
|
-
|
|
796
|
-
- `key` (string): The storage key.
|
|
797
|
-
|
|
798
|
-
**Returns**:
|
|
770
|
+
With hooks:
|
|
799
771
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
const value = await storeService.getAsync('key');
|
|
772
|
+
```ts
|
|
773
|
+
const token = await storeService.get("token", {
|
|
774
|
+
onSuccess: (v) => console.log(v),
|
|
775
|
+
onError: console.error,
|
|
776
|
+
});
|
|
806
777
|
```
|
|
807
778
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
Sets a JSON value in storage.
|
|
779
|
+
**Returns:** `Promise<string | null>`
|
|
811
780
|
|
|
812
|
-
|
|
781
|
+
---
|
|
813
782
|
|
|
814
|
-
|
|
815
|
-
- `value` (any): The value to store.
|
|
816
|
-
- `callback` (function): The callback to execute on success.
|
|
817
|
-
- `errCallback` (function): The callback to execute on error.
|
|
783
|
+
### setJson
|
|
818
784
|
|
|
819
|
-
|
|
785
|
+
Stores a JSON-serializable value.
|
|
820
786
|
|
|
821
|
-
```
|
|
822
|
-
storeService.setJson(
|
|
787
|
+
```ts
|
|
788
|
+
await storeService.setJson("profile", { name: "Den", role: "dev" });
|
|
823
789
|
```
|
|
824
790
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
Sets a JSON value in storage asynchronously.
|
|
828
|
-
|
|
829
|
-
**Parameters**:
|
|
830
|
-
|
|
831
|
-
- `key` (string): The storage key.
|
|
832
|
-
- `value` (any): The value to store.
|
|
833
|
-
|
|
834
|
-
**Returns**:
|
|
835
|
-
|
|
836
|
-
- `Promise<boolean>`: A promise that resolves to a boolean indicating success.
|
|
791
|
+
With hooks:
|
|
837
792
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
793
|
+
```ts
|
|
794
|
+
await storeService.setJson("profile", user, {
|
|
795
|
+
onSuccess: () => console.log("saved"),
|
|
796
|
+
onError: console.error,
|
|
797
|
+
});
|
|
842
798
|
```
|
|
843
799
|
|
|
844
|
-
|
|
800
|
+
**Returns:** `Promise<boolean>`
|
|
845
801
|
|
|
846
|
-
|
|
802
|
+
---
|
|
847
803
|
|
|
848
|
-
|
|
804
|
+
### getJson
|
|
849
805
|
|
|
850
|
-
|
|
851
|
-
- `callback` (function): The callback to execute with the retrieved value.
|
|
852
|
-
- `errCallback` (function): The callback to execute on error.
|
|
806
|
+
Retrieves a JSON value safely.
|
|
853
807
|
|
|
854
|
-
|
|
808
|
+
- empty or missing → `null` (or `defaultValue`)
|
|
809
|
+
- corrupted JSON → auto-cleared (by default)
|
|
855
810
|
|
|
856
|
-
```
|
|
857
|
-
|
|
811
|
+
```ts
|
|
812
|
+
const profile = await storeService.getJson<User>("profile");
|
|
858
813
|
```
|
|
859
814
|
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
Gets a JSON value from storage asynchronously.
|
|
863
|
-
|
|
864
|
-
**Parameters**:
|
|
865
|
-
|
|
866
|
-
- `key` (string): The storage key.
|
|
867
|
-
|
|
868
|
-
**Returns**:
|
|
869
|
-
|
|
870
|
-
- `Promise<T | null>`: A promise that resolves to the retrieved value.
|
|
871
|
-
|
|
872
|
-
**Example**:
|
|
815
|
+
With defaults and error handling:
|
|
873
816
|
|
|
874
|
-
```
|
|
875
|
-
const
|
|
817
|
+
```ts
|
|
818
|
+
const profile = await storeService.getJson<User>("profile", {
|
|
819
|
+
defaultValue: {},
|
|
820
|
+
onError: console.warn,
|
|
821
|
+
});
|
|
876
822
|
```
|
|
877
823
|
|
|
878
|
-
|
|
824
|
+
Disable auto-clean:
|
|
879
825
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
826
|
+
```ts
|
|
827
|
+
await storeService.getJson("profile", {
|
|
828
|
+
clearOnError: false,
|
|
829
|
+
});
|
|
830
|
+
```
|
|
883
831
|
|
|
884
|
-
|
|
885
|
-
- `callback` (function): The callback to execute on success.
|
|
886
|
-
- `errCallback` (function): The callback to execute on error.
|
|
832
|
+
**Returns:** `Promise<T | null>`
|
|
887
833
|
|
|
888
|
-
|
|
834
|
+
---
|
|
889
835
|
|
|
890
|
-
|
|
836
|
+
### remove
|
|
891
837
|
|
|
892
|
-
|
|
838
|
+
Removes a single key.
|
|
893
839
|
|
|
894
|
-
```
|
|
895
|
-
await storeService.remove(
|
|
840
|
+
```ts
|
|
841
|
+
await storeService.remove("token");
|
|
896
842
|
```
|
|
897
843
|
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
Clears all values from storage.
|
|
844
|
+
With hooks:
|
|
901
845
|
|
|
902
|
-
|
|
846
|
+
```ts
|
|
847
|
+
await storeService.remove("token", {
|
|
848
|
+
onSuccess: () => console.log("removed"),
|
|
849
|
+
onError: console.error,
|
|
850
|
+
});
|
|
851
|
+
```
|
|
903
852
|
|
|
904
|
-
|
|
905
|
-
- `errCallback` (function): The callback to execute on error.
|
|
853
|
+
**Returns:** `Promise<boolean>`
|
|
906
854
|
|
|
907
|
-
|
|
855
|
+
---
|
|
908
856
|
|
|
909
|
-
|
|
857
|
+
### clear
|
|
910
858
|
|
|
911
|
-
|
|
859
|
+
Clears all stored values.
|
|
912
860
|
|
|
913
|
-
```
|
|
914
|
-
await storeService.clear(
|
|
861
|
+
```ts
|
|
862
|
+
await storeService.clear();
|
|
915
863
|
```
|
|
916
864
|
|
|
917
|
-
|
|
865
|
+
With hooks:
|
|
918
866
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
867
|
+
```ts
|
|
868
|
+
await storeService.clear({
|
|
869
|
+
onSuccess: () => console.log("cleared"),
|
|
870
|
+
onError: console.error,
|
|
871
|
+
});
|
|
872
|
+
```
|
|
922
873
|
|
|
923
|
-
|
|
874
|
+
**Returns:** `Promise<boolean>`
|
|
924
875
|
|
|
925
|
-
|
|
876
|
+
---
|
|
926
877
|
|
|
927
|
-
|
|
878
|
+
### Options object
|
|
928
879
|
|
|
929
|
-
|
|
880
|
+
All methods accept an optional `options` parameter:
|
|
930
881
|
|
|
931
|
-
```
|
|
932
|
-
|
|
882
|
+
```ts
|
|
883
|
+
interface StoreOptions<T = unknown> {
|
|
884
|
+
onSuccess?: (value?: T | null) => void;
|
|
885
|
+
onError?: (err: unknown) => void;
|
|
886
|
+
defaultValue?: T; // getJson only
|
|
887
|
+
clearOnError?: boolean; // getJson only (default: true)
|
|
888
|
+
}
|
|
933
889
|
```
|
|
934
890
|
|
|
935
891
|
## [Meta Service](#meta-service)
|
|
@@ -2193,3 +2149,129 @@ ngOnInit() {
|
|
|
2193
2149
|
this.theme.setRadius("square");
|
|
2194
2150
|
}
|
|
2195
2151
|
```
|
|
2152
|
+
|
|
2153
|
+
## [Translation Service](#translation-service)
|
|
2154
|
+
|
|
2155
|
+
Wacom includes a lightweight, signal-based runtime translation engine built for Angular Signals.
|
|
2156
|
+
|
|
2157
|
+
It provides:
|
|
2158
|
+
|
|
2159
|
+
- reactive translations via `WritableSignal<string>`
|
|
2160
|
+
- zero-config fallback (source text renders until translated)
|
|
2161
|
+
- persistent storage (auto-hydrates from `StoreService`)
|
|
2162
|
+
- directive + pipe for ergonomic template usage
|
|
2163
|
+
- instant language switching without reload
|
|
2164
|
+
|
|
2165
|
+
Unlike compile-time Angular i18n, this works fully at runtime.
|
|
2166
|
+
|
|
2167
|
+
---
|
|
2168
|
+
|
|
2169
|
+
### Translation model
|
|
2170
|
+
|
|
2171
|
+
```ts
|
|
2172
|
+
export interface Translation {
|
|
2173
|
+
sourceText: string;
|
|
2174
|
+
text: string;
|
|
2175
|
+
}
|
|
2176
|
+
```
|
|
2177
|
+
|
|
2178
|
+
Each `sourceText` acts as both:
|
|
2179
|
+
|
|
2180
|
+
- translation key
|
|
2181
|
+
- default visible UI text (fallback)
|
|
2182
|
+
|
|
2183
|
+
---
|
|
2184
|
+
|
|
2185
|
+
### Basic usage (signal API)
|
|
2186
|
+
|
|
2187
|
+
```ts
|
|
2188
|
+
import { TranslationService } from "wacom";
|
|
2189
|
+
|
|
2190
|
+
private _translationService = inject(TranslationService);
|
|
2191
|
+
|
|
2192
|
+
title = this._translationService.translate("Create project");
|
|
2193
|
+
```
|
|
2194
|
+
|
|
2195
|
+
The returned value is a `WritableSignal<string>`.
|
|
2196
|
+
|
|
2197
|
+
If no translation exists yet, it renders:
|
|
2198
|
+
|
|
2199
|
+
```
|
|
2200
|
+
Create project
|
|
2201
|
+
```
|
|
2202
|
+
|
|
2203
|
+
automatically.
|
|
2204
|
+
|
|
2205
|
+
---
|
|
2206
|
+
|
|
2207
|
+
### Updating translations in bulk (language switch)
|
|
2208
|
+
|
|
2209
|
+
```ts
|
|
2210
|
+
this._translationService.setMany([
|
|
2211
|
+
{ sourceText: "Create project", text: "Створити проєкт" },
|
|
2212
|
+
{ sourceText: "Save", text: "Зберегти" },
|
|
2213
|
+
]);
|
|
2214
|
+
```
|
|
2215
|
+
|
|
2216
|
+
Behavior:
|
|
2217
|
+
|
|
2218
|
+
- provided keys update reactively
|
|
2219
|
+
- missing keys reset back to original text
|
|
2220
|
+
- state persists in storage
|
|
2221
|
+
|
|
2222
|
+
---
|
|
2223
|
+
|
|
2224
|
+
### Updating a single translation
|
|
2225
|
+
|
|
2226
|
+
```ts
|
|
2227
|
+
this._translationService.setOne({
|
|
2228
|
+
sourceText: "Save",
|
|
2229
|
+
text: "Зберегти",
|
|
2230
|
+
});
|
|
2231
|
+
```
|
|
2232
|
+
|
|
2233
|
+
Useful for:
|
|
2234
|
+
|
|
2235
|
+
- live editors
|
|
2236
|
+
- dynamic language loading
|
|
2237
|
+
- admin translation panels
|
|
2238
|
+
|
|
2239
|
+
---
|
|
2240
|
+
|
|
2241
|
+
### Translate pipe (template friendly)
|
|
2242
|
+
|
|
2243
|
+
```html
|
|
2244
|
+
<h1>{{ 'Create project' | translate }}</h1>
|
|
2245
|
+
```
|
|
2246
|
+
|
|
2247
|
+
Auto-reacts when translations change.
|
|
2248
|
+
|
|
2249
|
+
---
|
|
2250
|
+
|
|
2251
|
+
### Translate directive (zero-key mode)
|
|
2252
|
+
|
|
2253
|
+
Automatically uses element’s original rendered text as translation key.
|
|
2254
|
+
|
|
2255
|
+
```html
|
|
2256
|
+
<h1 translate>Create project</h1>
|
|
2257
|
+
<button translate>Save</button>
|
|
2258
|
+
```
|
|
2259
|
+
|
|
2260
|
+
Optional explicit key:
|
|
2261
|
+
|
|
2262
|
+
```html
|
|
2263
|
+
<h1 translate="Create project"></h1>
|
|
2264
|
+
```
|
|
2265
|
+
|
|
2266
|
+
> The directive replaces `textContent` and is SSR-safe.
|
|
2267
|
+
|
|
2268
|
+
---
|
|
2269
|
+
|
|
2270
|
+
### Persistence
|
|
2271
|
+
|
|
2272
|
+
Translations are automatically:
|
|
2273
|
+
|
|
2274
|
+
- hydrated from storage on startup
|
|
2275
|
+
- synced after every update
|
|
2276
|
+
|
|
2277
|
+
No extra config required.
|