@shoelace-style/localize 3.0.4 → 3.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.1.0
4
+
5
+ - Added `exists()` method to determine if a term and/or a fallback term exists [#17](https://github.com/shoelace-style/localize/issues/17)
6
+
3
7
  ## 3.0.4
4
8
 
5
9
  - Ensure return values of translation functions are always a string
package/dist/index.d.ts CHANGED
@@ -8,6 +8,10 @@ export interface Translation {
8
8
  export interface DefaultTranslation extends Translation {
9
9
  [key: string]: any;
10
10
  }
11
+ export interface ExistsOptions {
12
+ lang: string;
13
+ includeFallback: boolean;
14
+ }
11
15
  export declare function registerTranslation(...translation: Translation[]): void;
12
16
  export declare function update(): void;
13
17
  export declare class LocalizeController<UserTranslation extends Translation = DefaultTranslation> implements ReactiveController {
@@ -17,6 +21,8 @@ export declare class LocalizeController<UserTranslation extends Translation = De
17
21
  hostDisconnected(): void;
18
22
  dir(): string;
19
23
  lang(): string;
24
+ private getTranslationData;
25
+ exists<K extends keyof UserTranslation>(key: K, options: Partial<ExistsOptions>): boolean;
20
26
  term<K extends keyof UserTranslation>(key: K, ...args: FunctionParams<UserTranslation[K]>): string;
21
27
  date(dateToFormat: Date | string, options?: Intl.DateTimeFormatOptions): string;
22
28
  number(numberToFormat: number | string, options?: Intl.NumberFormatOptions): string;
package/dist/index.js CHANGED
@@ -49,13 +49,28 @@ export class LocalizeController {
49
49
  lang() {
50
50
  return `${this.host.lang || documentLanguage}`.toLowerCase();
51
51
  }
52
- term(key, ...args) {
52
+ getTranslationData(lang) {
53
53
  var _a, _b;
54
- const locale = new Intl.Locale(this.lang());
54
+ const locale = new Intl.Locale(lang);
55
55
  const language = locale === null || locale === void 0 ? void 0 : locale.language.toLowerCase();
56
56
  const region = (_b = (_a = locale === null || locale === void 0 ? void 0 : locale.region) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : '';
57
57
  const primary = translations.get(`${language}-${region}`);
58
58
  const secondary = translations.get(language);
59
+ return { locale, language, region, primary, secondary };
60
+ }
61
+ exists(key, options) {
62
+ var _a;
63
+ const { primary, secondary } = this.getTranslationData((_a = options.lang) !== null && _a !== void 0 ? _a : this.lang());
64
+ options = Object.assign({ includeFallback: false }, options);
65
+ if ((primary && primary[key]) ||
66
+ (secondary && secondary[key]) ||
67
+ (options.includeFallback && fallback && fallback[key])) {
68
+ return true;
69
+ }
70
+ return false;
71
+ }
72
+ term(key, ...args) {
73
+ const { primary, secondary } = this.getTranslationData(this.lang());
59
74
  let term;
60
75
  if (primary && primary[key]) {
61
76
  term = primary[key];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shoelace-style/localize",
3
- "version": "3.0.4",
3
+ "version": "3.1.0",
4
4
  "description": "A micro library for localizing custom elements using Lit's Reactive Controller model.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
package/src/index.ts CHANGED
@@ -12,6 +12,11 @@ export interface DefaultTranslation extends Translation {
12
12
  [key: string]: any;
13
13
  }
14
14
 
15
+ export interface ExistsOptions {
16
+ lang: string;
17
+ includeFallback: boolean;
18
+ }
19
+
15
20
  const connectedElements = new Set<HTMLElement>();
16
21
  const documentElementObserver = new MutationObserver(update);
17
22
  const translations: Map<string, Translation> = new Map();
@@ -25,9 +30,7 @@ documentElementObserver.observe(document.documentElement, {
25
30
  attributeFilter: ['dir', 'lang']
26
31
  });
27
32
 
28
- //
29
- // Registers one or more translations
30
- //
33
+ /** Registers one or more translations */
31
34
  export function registerTranslation(...translation: Translation[]) {
32
35
  translation.map(t => {
33
36
  const code = t.$code.toLowerCase();
@@ -48,9 +51,7 @@ export function registerTranslation(...translation: Translation[]) {
48
51
  update();
49
52
  }
50
53
 
51
- //
52
- // Updates all localized elements that are currently connected
53
- //
54
+ /** Updates all localized elements that are currently connected */
54
55
  export function update() {
55
56
  documentDirection = document.documentElement.dir || 'ltr';
56
57
  documentLanguage = document.documentElement.lang || navigator.language;
@@ -62,25 +63,25 @@ export function update() {
62
63
  });
63
64
  }
64
65
 
65
- //
66
- // Reactive controller
67
- //
68
- // To use this controller, import the class and instantiate it in a custom element constructor:
69
- //
70
- // private localize = new LocalizeController(this);
71
- //
72
- // This will add the element to the set and make it respond to changes to <html dir|lang> automatically. To make it
73
- // respond to changes to its own dir|lang properties, make it a property:
74
- //
75
- // @property() dir: string;
76
- // @property() lang: string;
77
- //
78
- // To use a translation method, call it like this:
79
- //
80
- // ${this.localize.term('term_key_here')}
81
- // ${this.localize.date('2021-12-03')}
82
- // ${this.localize.number(1000000)}
83
- //
66
+ /**
67
+ * Localize Reactive Controller for components built with Lit
68
+ *
69
+ * To use this controller, import the class and instantiate it in a custom element constructor:
70
+ *
71
+ * private localize = new LocalizeController(this);
72
+ *
73
+ * This will add the element to the set and make it respond to changes to <html dir|lang> automatically. To make it
74
+ * respond to changes to its own dir|lang properties, make it a property:
75
+ *
76
+ * @property() dir: string;
77
+ * @property() lang: string;
78
+ *
79
+ * To use a translation method, call it like this:
80
+ *
81
+ * ${this.localize.term('term_key_here')}
82
+ * ${this.localize.date('2021-12-03')}
83
+ * ${this.localize.number(1000000)}
84
+ */
84
85
  export class LocalizeController<UserTranslation extends Translation = DefaultTranslation>
85
86
  implements ReactiveController
86
87
  {
@@ -115,12 +116,39 @@ export class LocalizeController<UserTranslation extends Translation = DefaultTra
115
116
  return `${this.host.lang || documentLanguage}`.toLowerCase();
116
117
  }
117
118
 
118
- term<K extends keyof UserTranslation>(key: K, ...args: FunctionParams<UserTranslation[K]>): string {
119
- const locale = new Intl.Locale(this.lang());
119
+ private getTranslationData(lang: string) {
120
+ const locale = new Intl.Locale(lang);
120
121
  const language = locale?.language.toLowerCase();
121
122
  const region = locale?.region?.toLowerCase() ?? '';
122
123
  const primary = <UserTranslation>translations.get(`${language}-${region}`);
123
124
  const secondary = <UserTranslation>translations.get(language);
125
+
126
+ return { locale, language, region, primary, secondary };
127
+ }
128
+
129
+ /** Determines if the specified term exists, optionally checking the fallback translation. */
130
+ exists<K extends keyof UserTranslation>(key: K, options: Partial<ExistsOptions>): boolean {
131
+ const { primary, secondary } = this.getTranslationData(options.lang ?? this.lang());
132
+
133
+ options = {
134
+ includeFallback: false,
135
+ ...options
136
+ };
137
+
138
+ if (
139
+ (primary && primary[key]) ||
140
+ (secondary && secondary[key]) ||
141
+ (options.includeFallback && fallback && fallback[key as keyof Translation])
142
+ ) {
143
+ return true;
144
+ }
145
+
146
+ return false;
147
+ }
148
+
149
+ /** Outputs a translated term. */
150
+ term<K extends keyof UserTranslation>(key: K, ...args: FunctionParams<UserTranslation[K]>): string {
151
+ const { primary, secondary } = this.getTranslationData(this.lang());
124
152
  let term: any;
125
153
 
126
154
  // Look for a matching term using regionCode, code, then the fallback