piral-translate 1.4.0-beta.6257 → 1.4.0-beta.6276

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/esm/create.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { PiralPlugin } from 'piral-core';
2
- import { PiletLocaleApi, LocalizationMessages, Localizable } from './types';
2
+ import { PiletLocaleApi, LocalizationMessages, Localizable, NestedLocalizationMessages } from './types';
3
3
  export interface TranslationFallback {
4
4
  (key: string, language: string): string;
5
5
  }
@@ -14,7 +14,7 @@ export interface LocaleConfig {
14
14
  * Sets the default (global) localization messages.
15
15
  * @default {}
16
16
  */
17
- messages?: LocalizationMessages;
17
+ messages?: LocalizationMessages | NestedLocalizationMessages;
18
18
  /**
19
19
  * Sets the default language to use.
20
20
  */
package/esm/create.js CHANGED
@@ -2,6 +2,7 @@ import * as deepmerge from 'deepmerge';
2
2
  import { createActions } from './actions';
3
3
  import { Localizer } from './localize';
4
4
  import { DefaultPicker } from './default';
5
+ import { flattenTranslations } from './flatten-translations';
5
6
  /**
6
7
  * Sets up a new localizer by using the given config.
7
8
  * @param config The configuration for the new localizer.
@@ -60,7 +61,7 @@ export function createLocaleApi(localizer = setupLocalizer()) {
60
61
  return selected;
61
62
  },
62
63
  setTranslations(messages) {
63
- localTranslations = messages;
64
+ localTranslations = flattenTranslations(messages);
64
65
  },
65
66
  getTranslations() {
66
67
  return localTranslations;
package/esm/create.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,WAAW,CAAC;AAGvC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AA8B1C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,SAAuB,EAAE;IACtD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IACnC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACzC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC;IACpC,MAAM,QAAQ,GAAG,OAAO,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IAC7G,MAAM,QAAQ,GAAG,QAAQ,IAAI,WAAW,CAAC;IACzC,OAAO,IAAI,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;AACnG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,YAAyB,cAAc,EAAE;IACvE,OAAO,CAAC,OAAO,EAAE,EAAE;QACjB,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;QAEhD,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC3B,GAAG,KAAK;YACR,UAAU,EAAE;gBACV,eAAe,EAAE,aAAa;gBAC9B,GAAG,KAAK,CAAC,UAAU;aACpB;YACD,QAAQ,EAAE;gBACR,OAAO,EAAE,KAAK;gBACd,SAAS,EAAE,SAAS,CAAC,SAAS;gBAC9B,QAAQ,EAAE,SAAS,CAAC,QAAQ;aAC7B;SACF,CAAC,CAAC,CAAC;QAEJ,OAAO,CAAC,GAAG,EAAE,EAAE;YACb,IAAI,iBAAiB,GAAyB,EAAE,CAAC;YAEjD,OAAO;gBACL,eAAe,CAAC,QAAgC,EAAE,eAAwB,IAAI;oBAC5E,MAAM,eAAe,GAA2B,QAAQ,CAAC;oBAEzD,IAAI,YAAY,EAAE;wBAChB,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;qBAC7C;yBAAM;wBACL,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;qBAC1C;oBAED,IAAI,CAAC,eAAe,CAClB,SAAS,CAAC,GAAG,CAAC,eAAe,CAAC,CAC/B,CAAC;gBACJ,CAAC;gBACD,kBAAkB,CAAC,EAAwB;oBACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBAE/D,IAAI,EAAE,EAAE;wBACN,EAAE,CAAC,QAAQ,CAAC,CAAC;wBACb,MAAM,OAAO,GAAG,CAAC,EAA4B,EAAE,EAAE;4BAC/C,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC;wBACzB,CAAC,CAAC;wBACF,GAAG,CAAC,EAAE,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;wBACnC,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;qBAClD;oBAED,OAAO,QAAQ,CAAC;gBAClB,CAAC;gBACD,eAAe,CAAC,QAAQ;oBACtB,iBAAiB,GAAG,QAAQ,CAAC;gBAC/B,CAAC;gBACD,eAAe;oBACb,OAAO,iBAAiB,CAAC;gBAC3B,CAAC;gBACD,SAAS,CAAC,GAAG,EAAE,SAAS;oBACtB,OAAO,SAAS,CAAC,aAAa,CAAC,iBAAiB,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;gBACpE,CAAC;aACF,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { LocalizationMessages, NestedLocalizationMessages } from './types';
2
+ export declare function flattenTranslations(messages: LocalizationMessages | NestedLocalizationMessages): LocalizationMessages;
@@ -0,0 +1,32 @@
1
+ export function flattenTranslations(messages) {
2
+ return Object.fromEntries(Object
3
+ .entries(messages)
4
+ .map(([language, translations]) => {
5
+ return [
6
+ language,
7
+ flat(translations)
8
+ ];
9
+ }));
10
+ }
11
+ function flat(source) {
12
+ const target = {};
13
+ flatten(source, target);
14
+ return target;
15
+ }
16
+ function flatten(source, target, prop = '') {
17
+ if (typeof source === 'string') {
18
+ target[prop] = source;
19
+ return;
20
+ }
21
+ if (typeof source === 'object' && source !== null) {
22
+ Object
23
+ .keys(source)
24
+ .forEach((key) => {
25
+ flatten(source[key], target, prop
26
+ ? `${prop}.${key}`
27
+ : key);
28
+ });
29
+ return;
30
+ }
31
+ }
32
+ //# sourceMappingURL=flatten-translations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flatten-translations.js","sourceRoot":"","sources":["../src/flatten-translations.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,mBAAmB,CAAC,QAA2D;IAC7F,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM;SACH,OAAO,CAAC,QAAQ,CAAC;SACjB,GAAG,CAAC,CAAC,CAAE,QAAQ,EAAE,YAAY,CAAE,EAAE,EAAE;QAClC,OAAO;YACL,QAAQ;YACR,IAAI,CAAC,YAAY,CAAC;SACnB,CAAA;IACH,CAAC,CAAC,CACL,CAAC;AACJ,CAAC;AAED,SAAS,IAAI,CAAC,MAA+B;IAC3C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAExB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,OAAO,CAAC,MAAW,EAAE,MAA8B,EAAE,IAAI,GAAG,EAAE;IACrE,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;QAEtB,OAAO;KACR;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE;QACjD,MAAM;aACH,IAAI,CAAC,MAAM,CAAC;aACZ,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACf,OAAO,CACL,MAAM,CAAC,GAAG,CAAC,EACX,MAAM,EACN,IAAI;gBACF,CAAC,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE;gBAClB,CAAC,CAAC,GAAG,CACR,CAAC;QACJ,CAAC,CAAC,CAAC;QAEL,OAAO;KACR;AACH,CAAC"}
package/esm/localize.d.ts CHANGED
@@ -1,14 +1,14 @@
1
- import { LocalizationMessages, Localizable } from './types';
1
+ import { LocalizationMessages, Localizable, NestedLocalizationMessages } from './types';
2
2
  declare function defaultFallback(key: string, language: string): string;
3
3
  export declare class Localizer implements Localizable {
4
- messages: LocalizationMessages;
5
4
  language: string;
6
5
  languages: Array<string>;
7
6
  private fallback;
7
+ messages: LocalizationMessages;
8
8
  /**
9
9
  * Creates a new instance of a localizer.
10
10
  */
11
- constructor(messages: LocalizationMessages, language: string, languages: Array<string>, fallback?: typeof defaultFallback);
11
+ constructor(messages: LocalizationMessages | NestedLocalizationMessages, language: string, languages: Array<string>, fallback?: typeof defaultFallback);
12
12
  /**
13
13
  * Localizes the given key via the global translations.
14
14
  * @param key The key of the translation snippet.
package/esm/localize.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { flattenTranslations } from './flatten-translations';
1
2
  function defaultFallback(key, language) {
2
3
  if (process.env.NODE_ENV === 'production') {
3
4
  return language ? '...' : '';
@@ -22,10 +23,10 @@ export class Localizer {
22
23
  * Creates a new instance of a localizer.
23
24
  */
24
25
  constructor(messages, language, languages, fallback = defaultFallback) {
25
- this.messages = messages;
26
26
  this.language = language;
27
27
  this.languages = languages;
28
28
  this.fallback = fallback;
29
+ this.messages = flattenTranslations(messages);
29
30
  }
30
31
  /**
31
32
  * Localizes the given key via the global translations.
@@ -1 +1 @@
1
- {"version":3,"file":"localize.js","sourceRoot":"","sources":["../src/localize.ts"],"names":[],"mappings":"AAEA,SAAS,eAAe,CAAC,GAAW,EAAE,QAAgB;IACpD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;QACzC,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B;SAAM;QACL,IAAI,QAAQ,EAAE;YACZ,OAAO,CAAC,IAAI,CAAC,2BAA2B,GAAG,kBAAkB,QAAQ,IAAI,CAAC,CAAC;YAC3E,OAAO,KAAK,QAAQ,IAAI,GAAG,IAAI,CAAC;SACjC;aAAM;YACL,OAAO,EAAE,CAAC;SACX;KACF;AACH,CAAC;AAED,SAAS,aAAa,CAAmB,OAAe,EAAE,SAAY;IACpE,OAAO,OAAO,CAAC,OAAO,CAAC,6BAA6B,EAAE,CAAC,MAAc,EAAE,EAAU,EAAE,EAAE;QACnF,OAAO,EAAE,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,OAAO,SAAS;IACpB;;OAEG;IACH,YACS,QAA8B,EAC9B,QAAgB,EAChB,SAAwB,EACvB,WAAW,eAAe;QAH3B,aAAQ,GAAR,QAAQ,CAAsB;QAC9B,aAAQ,GAAR,QAAQ,CAAQ;QAChB,cAAS,GAAT,SAAS,CAAe;QACvB,aAAQ,GAAR,QAAQ,CAAkB;IACjC,CAAC;IAEJ;;;;OAIG;IACI,cAAc,CAAmB,GAAW,EAAE,SAAa;QAChE,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACI,aAAa,CAAmB,aAAmC,EAAE,GAAW,EAAE,SAAa;QACpG,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAErE,IAAI,OAAO,KAAK,SAAS,EAAE;YACzB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;SAC1C;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,YAAY,CAAmB,GAAW,EAAE,SAAa;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAErE,IAAI,OAAO,KAAK,SAAS,EAAE;YACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;SAC1C;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,gBAAgB,CAAmB,QAA8B,EAAE,GAAW,EAAE,SAAa;QACnG,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,MAAM,YAAY,GAAG,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,YAAY,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;QACtD,OAAO,WAAW,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC1F,CAAC;CACF"}
1
+ {"version":3,"file":"localize.js","sourceRoot":"","sources":["../src/localize.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,SAAS,eAAe,CAAC,GAAW,EAAE,QAAgB;IACpD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;QACzC,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B;SAAM;QACL,IAAI,QAAQ,EAAE;YACZ,OAAO,CAAC,IAAI,CAAC,2BAA2B,GAAG,kBAAkB,QAAQ,IAAI,CAAC,CAAC;YAC3E,OAAO,KAAK,QAAQ,IAAI,GAAG,IAAI,CAAC;SACjC;aAAM;YACL,OAAO,EAAE,CAAC;SACX;KACF;AACH,CAAC;AAED,SAAS,aAAa,CAAmB,OAAe,EAAE,SAAY;IACpE,OAAO,OAAO,CAAC,OAAO,CAAC,6BAA6B,EAAE,CAAC,MAAc,EAAE,EAAU,EAAE,EAAE;QACnF,OAAO,EAAE,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,OAAO,SAAS;IAGpB;;OAEG;IACH,YACE,QAA2D,EACpD,QAAgB,EAChB,SAAwB,EACvB,WAAW,eAAe;QAF3B,aAAQ,GAAR,QAAQ,CAAQ;QAChB,cAAS,GAAT,SAAS,CAAe;QACvB,aAAQ,GAAR,QAAQ,CAAkB;QAElC,IAAI,CAAC,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED;;;;OAIG;IACI,cAAc,CAAmB,GAAW,EAAE,SAAa;QAChE,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACI,aAAa,CAAmB,aAAmC,EAAE,GAAW,EAAE,SAAa;QACpG,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAErE,IAAI,OAAO,KAAK,SAAS,EAAE;YACzB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;SAC1C;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,YAAY,CAAmB,GAAW,EAAE,SAAa;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAErE,IAAI,OAAO,KAAK,SAAS,EAAE;YACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;SAC1C;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,gBAAgB,CAAmB,QAA8B,EAAE,GAAW,EAAE,SAAa;QACnG,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,MAAM,YAAY,GAAG,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,YAAY,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;QACtD,OAAO,WAAW,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC1F,CAAC;CACF"}
package/esm/types.d.ts CHANGED
@@ -91,6 +91,12 @@ export interface Translations {
91
91
  */
92
92
  [tag: string]: string;
93
93
  }
94
+ export interface NestedTranslations {
95
+ /**
96
+ * The available wordings (tag to translation or nested translations).
97
+ */
98
+ [tag: string]: string | NestedTranslations;
99
+ }
94
100
  export interface LanguageLoader {
95
101
  (language: string, current: LanguageData): Promise<LanguageData>;
96
102
  }
@@ -107,6 +113,12 @@ export interface LocalizationMessages {
107
113
  */
108
114
  [lang: string]: Translations;
109
115
  }
116
+ export interface NestedLocalizationMessages {
117
+ /**
118
+ * The available languages (lang to wordings or nested wordings).
119
+ */
120
+ [lang: string]: NestedTranslations;
121
+ }
110
122
  export interface PiletLocaleApi {
111
123
  /**
112
124
  * Adds a list of translations to the existing translations.
@@ -117,7 +129,7 @@ export interface PiletLocaleApi {
117
129
  * @param messagesList The list of messages that extend the existing translations
118
130
  * @param [isOverriding=true] Indicates whether the new translations overwrite the existing translations
119
131
  */
120
- addTranslations(messagesList: LocalizationMessages[], isOverriding?: boolean): void;
132
+ addTranslations(messagesList: (LocalizationMessages | NestedLocalizationMessages)[], isOverriding?: boolean): void;
121
133
  /**
122
134
  * Gets the currently selected language directly.
123
135
  */
@@ -139,7 +151,7 @@ export interface PiletLocaleApi {
139
151
  * The translations will be exclusively used for retrieving translations for the pilet.
140
152
  * @param messages The messages to use as translation basis.
141
153
  */
142
- setTranslations(messages: LocalizationMessages): void;
154
+ setTranslations(messages: LocalizationMessages | NestedLocalizationMessages): void;
143
155
  /**
144
156
  * Gets the currently provided translations by the pilet.
145
157
  */
package/lib/create.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { PiralPlugin } from 'piral-core';
2
- import { PiletLocaleApi, LocalizationMessages, Localizable } from './types';
2
+ import { PiletLocaleApi, LocalizationMessages, Localizable, NestedLocalizationMessages } from './types';
3
3
  export interface TranslationFallback {
4
4
  (key: string, language: string): string;
5
5
  }
@@ -14,7 +14,7 @@ export interface LocaleConfig {
14
14
  * Sets the default (global) localization messages.
15
15
  * @default {}
16
16
  */
17
- messages?: LocalizationMessages;
17
+ messages?: LocalizationMessages | NestedLocalizationMessages;
18
18
  /**
19
19
  * Sets the default language to use.
20
20
  */
package/lib/create.js CHANGED
@@ -5,6 +5,7 @@ const deepmerge = require("deepmerge");
5
5
  const actions_1 = require("./actions");
6
6
  const localize_1 = require("./localize");
7
7
  const default_1 = require("./default");
8
+ const flatten_translations_1 = require("./flatten-translations");
8
9
  /**
9
10
  * Sets up a new localizer by using the given config.
10
11
  * @param config The configuration for the new localizer.
@@ -64,7 +65,7 @@ function createLocaleApi(localizer = setupLocalizer()) {
64
65
  return selected;
65
66
  },
66
67
  setTranslations(messages) {
67
- localTranslations = messages;
68
+ localTranslations = (0, flatten_translations_1.flattenTranslations)(messages);
68
69
  },
69
70
  getTranslations() {
70
71
  return localTranslations;
package/lib/create.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { LocalizationMessages, NestedLocalizationMessages } from './types';
2
+ export declare function flattenTranslations(messages: LocalizationMessages | NestedLocalizationMessages): LocalizationMessages;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.flattenTranslations = void 0;
4
+ function flattenTranslations(messages) {
5
+ return Object.fromEntries(Object
6
+ .entries(messages)
7
+ .map(([language, translations]) => {
8
+ return [
9
+ language,
10
+ flat(translations)
11
+ ];
12
+ }));
13
+ }
14
+ exports.flattenTranslations = flattenTranslations;
15
+ function flat(source) {
16
+ const target = {};
17
+ flatten(source, target);
18
+ return target;
19
+ }
20
+ function flatten(source, target, prop = '') {
21
+ if (typeof source === 'string') {
22
+ target[prop] = source;
23
+ return;
24
+ }
25
+ if (typeof source === 'object' && source !== null) {
26
+ Object
27
+ .keys(source)
28
+ .forEach((key) => {
29
+ flatten(source[key], target, prop
30
+ ? `${prop}.${key}`
31
+ : key);
32
+ });
33
+ return;
34
+ }
35
+ }
36
+ //# sourceMappingURL=flatten-translations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flatten-translations.js","sourceRoot":"","sources":["../src/flatten-translations.ts"],"names":[],"mappings":";;;AAEA,SAAgB,mBAAmB,CAAC,QAA2D;IAC7F,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM;SACH,OAAO,CAAC,QAAQ,CAAC;SACjB,GAAG,CAAC,CAAC,CAAE,QAAQ,EAAE,YAAY,CAAE,EAAE,EAAE;QAClC,OAAO;YACL,QAAQ;YACR,IAAI,CAAC,YAAY,CAAC;SACnB,CAAA;IACH,CAAC,CAAC,CACL,CAAC;AACJ,CAAC;AAXD,kDAWC;AAED,SAAS,IAAI,CAAC,MAA+B;IAC3C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAExB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,OAAO,CAAC,MAAW,EAAE,MAA8B,EAAE,IAAI,GAAG,EAAE;IACrE,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;QAEtB,OAAO;KACR;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE;QACjD,MAAM;aACH,IAAI,CAAC,MAAM,CAAC;aACZ,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACf,OAAO,CACL,MAAM,CAAC,GAAG,CAAC,EACX,MAAM,EACN,IAAI;gBACF,CAAC,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE;gBAClB,CAAC,CAAC,GAAG,CACR,CAAC;QACJ,CAAC,CAAC,CAAC;QAEL,OAAO;KACR;AACH,CAAC"}
package/lib/localize.d.ts CHANGED
@@ -1,14 +1,14 @@
1
- import { LocalizationMessages, Localizable } from './types';
1
+ import { LocalizationMessages, Localizable, NestedLocalizationMessages } from './types';
2
2
  declare function defaultFallback(key: string, language: string): string;
3
3
  export declare class Localizer implements Localizable {
4
- messages: LocalizationMessages;
5
4
  language: string;
6
5
  languages: Array<string>;
7
6
  private fallback;
7
+ messages: LocalizationMessages;
8
8
  /**
9
9
  * Creates a new instance of a localizer.
10
10
  */
11
- constructor(messages: LocalizationMessages, language: string, languages: Array<string>, fallback?: typeof defaultFallback);
11
+ constructor(messages: LocalizationMessages | NestedLocalizationMessages, language: string, languages: Array<string>, fallback?: typeof defaultFallback);
12
12
  /**
13
13
  * Localizes the given key via the global translations.
14
14
  * @param key The key of the translation snippet.
package/lib/localize.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Localizer = void 0;
4
+ const flatten_translations_1 = require("./flatten-translations");
4
5
  function defaultFallback(key, language) {
5
6
  if (process.env.NODE_ENV === 'production') {
6
7
  return language ? '...' : '';
@@ -25,10 +26,10 @@ class Localizer {
25
26
  * Creates a new instance of a localizer.
26
27
  */
27
28
  constructor(messages, language, languages, fallback = defaultFallback) {
28
- this.messages = messages;
29
29
  this.language = language;
30
30
  this.languages = languages;
31
31
  this.fallback = fallback;
32
+ this.messages = (0, flatten_translations_1.flattenTranslations)(messages);
32
33
  }
33
34
  /**
34
35
  * Localizes the given key via the global translations.
@@ -1 +1 @@
1
- {"version":3,"file":"localize.js","sourceRoot":"","sources":["../src/localize.ts"],"names":[],"mappings":";;;AAEA,SAAS,eAAe,CAAC,GAAW,EAAE,QAAgB;IACpD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;QACzC,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B;SAAM;QACL,IAAI,QAAQ,EAAE;YACZ,OAAO,CAAC,IAAI,CAAC,2BAA2B,GAAG,kBAAkB,QAAQ,IAAI,CAAC,CAAC;YAC3E,OAAO,KAAK,QAAQ,IAAI,GAAG,IAAI,CAAC;SACjC;aAAM;YACL,OAAO,EAAE,CAAC;SACX;KACF;AACH,CAAC;AAED,SAAS,aAAa,CAAmB,OAAe,EAAE,SAAY;IACpE,OAAO,OAAO,CAAC,OAAO,CAAC,6BAA6B,EAAE,CAAC,MAAc,EAAE,EAAU,EAAE,EAAE;QACnF,OAAO,EAAE,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAa,SAAS;IACpB;;OAEG;IACH,YACS,QAA8B,EAC9B,QAAgB,EAChB,SAAwB,EACvB,WAAW,eAAe;QAH3B,aAAQ,GAAR,QAAQ,CAAsB;QAC9B,aAAQ,GAAR,QAAQ,CAAQ;QAChB,cAAS,GAAT,SAAS,CAAe;QACvB,aAAQ,GAAR,QAAQ,CAAkB;IACjC,CAAC;IAEJ;;;;OAIG;IACI,cAAc,CAAmB,GAAW,EAAE,SAAa;QAChE,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACI,aAAa,CAAmB,aAAmC,EAAE,GAAW,EAAE,SAAa;QACpG,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAErE,IAAI,OAAO,KAAK,SAAS,EAAE;YACzB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;SAC1C;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,YAAY,CAAmB,GAAW,EAAE,SAAa;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAErE,IAAI,OAAO,KAAK,SAAS,EAAE;YACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;SAC1C;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,gBAAgB,CAAmB,QAA8B,EAAE,GAAW,EAAE,SAAa;QACnG,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,MAAM,YAAY,GAAG,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,YAAY,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;QACtD,OAAO,WAAW,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC1F,CAAC;CACF;AArDD,8BAqDC"}
1
+ {"version":3,"file":"localize.js","sourceRoot":"","sources":["../src/localize.ts"],"names":[],"mappings":";;;AACA,iEAA6D;AAE7D,SAAS,eAAe,CAAC,GAAW,EAAE,QAAgB;IACpD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;QACzC,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B;SAAM;QACL,IAAI,QAAQ,EAAE;YACZ,OAAO,CAAC,IAAI,CAAC,2BAA2B,GAAG,kBAAkB,QAAQ,IAAI,CAAC,CAAC;YAC3E,OAAO,KAAK,QAAQ,IAAI,GAAG,IAAI,CAAC;SACjC;aAAM;YACL,OAAO,EAAE,CAAC;SACX;KACF;AACH,CAAC;AAED,SAAS,aAAa,CAAmB,OAAe,EAAE,SAAY;IACpE,OAAO,OAAO,CAAC,OAAO,CAAC,6BAA6B,EAAE,CAAC,MAAc,EAAE,EAAU,EAAE,EAAE;QACnF,OAAO,EAAE,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAa,SAAS;IAGpB;;OAEG;IACH,YACE,QAA2D,EACpD,QAAgB,EAChB,SAAwB,EACvB,WAAW,eAAe;QAF3B,aAAQ,GAAR,QAAQ,CAAQ;QAChB,cAAS,GAAT,SAAS,CAAe;QACvB,aAAQ,GAAR,QAAQ,CAAkB;QAElC,IAAI,CAAC,QAAQ,GAAG,IAAA,0CAAmB,EAAC,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED;;;;OAIG;IACI,cAAc,CAAmB,GAAW,EAAE,SAAa;QAChE,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACI,aAAa,CAAmB,aAAmC,EAAE,GAAW,EAAE,SAAa;QACpG,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAErE,IAAI,OAAO,KAAK,SAAS,EAAE;YACzB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;SAC1C;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,YAAY,CAAmB,GAAW,EAAE,SAAa;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;QAErE,IAAI,OAAO,KAAK,SAAS,EAAE;YACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;SAC1C;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,gBAAgB,CAAmB,QAA8B,EAAE,GAAW,EAAE,SAAa;QACnG,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,MAAM,YAAY,GAAG,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,YAAY,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;QACtD,OAAO,WAAW,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC1F,CAAC;CACF;AAzDD,8BAyDC"}
package/lib/types.d.ts CHANGED
@@ -91,6 +91,12 @@ export interface Translations {
91
91
  */
92
92
  [tag: string]: string;
93
93
  }
94
+ export interface NestedTranslations {
95
+ /**
96
+ * The available wordings (tag to translation or nested translations).
97
+ */
98
+ [tag: string]: string | NestedTranslations;
99
+ }
94
100
  export interface LanguageLoader {
95
101
  (language: string, current: LanguageData): Promise<LanguageData>;
96
102
  }
@@ -107,6 +113,12 @@ export interface LocalizationMessages {
107
113
  */
108
114
  [lang: string]: Translations;
109
115
  }
116
+ export interface NestedLocalizationMessages {
117
+ /**
118
+ * The available languages (lang to wordings or nested wordings).
119
+ */
120
+ [lang: string]: NestedTranslations;
121
+ }
110
122
  export interface PiletLocaleApi {
111
123
  /**
112
124
  * Adds a list of translations to the existing translations.
@@ -117,7 +129,7 @@ export interface PiletLocaleApi {
117
129
  * @param messagesList The list of messages that extend the existing translations
118
130
  * @param [isOverriding=true] Indicates whether the new translations overwrite the existing translations
119
131
  */
120
- addTranslations(messagesList: LocalizationMessages[], isOverriding?: boolean): void;
132
+ addTranslations(messagesList: (LocalizationMessages | NestedLocalizationMessages)[], isOverriding?: boolean): void;
121
133
  /**
122
134
  * Gets the currently selected language directly.
123
135
  */
@@ -139,7 +151,7 @@ export interface PiletLocaleApi {
139
151
  * The translations will be exclusively used for retrieving translations for the pilet.
140
152
  * @param messages The messages to use as translation basis.
141
153
  */
142
- setTranslations(messages: LocalizationMessages): void;
154
+ setTranslations(messages: LocalizationMessages | NestedLocalizationMessages): void;
143
155
  /**
144
156
  * Gets the currently provided translations by the pilet.
145
157
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "piral-translate",
3
- "version": "1.4.0-beta.6257",
3
+ "version": "1.4.0-beta.6276",
4
4
  "description": "Plugin for providing translated messages in Piral.",
5
5
  "keywords": [
6
6
  "piral",
@@ -68,8 +68,8 @@
68
68
  "devDependencies": {
69
69
  "@types/deepmerge": "^2.2.0",
70
70
  "@types/react": "^18.0.0",
71
- "piral-core": "1.4.0-beta.6257",
71
+ "piral-core": "1.4.0-beta.6276",
72
72
  "react": "^18.0.0"
73
73
  },
74
- "gitHead": "2243cd98b8f72426a79b14582af41154b10f7883"
74
+ "gitHead": "c39d667e798b9b2dd48a3456ab966f4e7671e368"
75
75
  }
@@ -1 +1 @@
1
- var piralTranslate=(()=>{var k=Object.create;var p=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var I=Object.getPrototypeOf,R=Object.prototype.hasOwnProperty;var T=e=>p(e,"__esModule",{value:!0});var l=(e=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(e,{get:(t,r)=>(typeof require!="undefined"?require:t)[r]}):e)(function(e){if(typeof require!="undefined")return require.apply(this,arguments);throw new Error('Dynamic require of "'+e+'" is not supported')});var F=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),U=(e,t)=>{T(e);for(var r in t)p(e,r,{get:t[r],enumerable:!0})},$=(e,t,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of G(t))!R.call(e,a)&&a!=="default"&&p(e,a,{get:()=>t[a],enumerable:!(r=w(t,a))||r.enumerable});return e},i=e=>$(T(p(e!=null?k(I(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var j=F((ue,O)=>{"use strict";var D=function(t){return N(t)&&!B(t)};function N(e){return!!e&&typeof e=="object"}function B(e){var t=Object.prototype.toString.call(e);return t==="[object RegExp]"||t==="[object Date]"||Y(e)}var V=typeof Symbol=="function"&&Symbol.for,K=V?Symbol.for("react.element"):60103;function Y(e){return e.$$typeof===K}function Z(e){return Array.isArray(e)?[]:{}}function g(e,t){return t.clone!==!1&&t.isMergeableObject(e)?c(Z(e),e,t):e}function q(e,t,r){return e.concat(t).map(function(a){return g(a,r)})}function H(e,t){if(!t.customMerge)return c;var r=t.customMerge(e);return typeof r=="function"?r:c}function J(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(t){return Object.propertyIsEnumerable.call(e,t)}):[]}function x(e){return Object.keys(e).concat(J(e))}function h(e,t){try{return t in e}catch{return!1}}function Q(e,t){return h(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))}function W(e,t,r){var a={};return r.isMergeableObject(e)&&x(e).forEach(function(n){a[n]=g(e[n],r)}),x(t).forEach(function(n){Q(e,n)||(h(e,n)&&r.isMergeableObject(t[n])?a[n]=H(n,r)(e[n],t[n],r):a[n]=g(t[n],r))}),a}function c(e,t,r){r=r||{},r.arrayMerge=r.arrayMerge||q,r.isMergeableObject=r.isMergeableObject||D,r.cloneUnlessOtherwiseSpecified=g;var a=Array.isArray(t),n=Array.isArray(e),s=a===n;return s?a?r.arrayMerge(e,t,r):W(e,t,r):g(t,r)}c.all=function(t,r){if(!Array.isArray(t))throw new Error("first argument should be an array");return t.reduce(function(a,n){return c(a,n,r)},{})};var X=c;O.exports=X});var le={};U(le,{Languages:()=>ie,PiralLanguagesPicker:()=>L,createLocaleApi:()=>re,getUserLocale:()=>ne,setupLocalizer:()=>z,useDynamicLanguage:()=>se,useTranslate:()=>oe});var M=i(l("piral-core")),L=(0,M.getPiralComponent)("LanguagesPicker");var v=i(j());function P(e){return{selectLanguage(t,r){t.dispatch(a=>{e.language=r;let n=a.language.selected,s=r;return setTimeout(()=>{t.emit("select-language",{previousLanguage:n,currentLanguage:s})},0),{...a,language:{...a.language,loading:r===void 0,selected:r}}})},translate(t,r,a){return e&&e.localizeGlobal(r,a)},setTranslations(t,r,a){e.messages[r]=a.global;for(let n of a.locals){let s=t.apis[n.name];if(s){let o=s.getTranslations();o[r]=n.value,s.setTranslations(o)}}},getTranslations(t,r){return{global:e.messages[r],locals:Object.keys(t.apis).map(a=>({name:a,value:t.apis[a].getTranslations()[r]}))}}}}function ee(e,t){return t?"...":""}function te(e,t){return e.replace(/{{\s*([A-Za-z0-9_.]+)\s*}}/g,(r,a)=>a in t?t[a]||"":`{{${a}}}`)}var y=class{constructor(t,r,a,n=ee){this.messages=t;this.language=r;this.languages=a;this.fallback=n}localizeGlobal(t,r){return this.localizeBase(t,r)}localizeLocal(t,r,a){let n=this.translateMessage(t,r,a);return n===void 0?this.localizeBase(r,a):n}localizeBase(t,r){let a=this.translateMessage(this.messages,t,r);return a===void 0?this.fallback(t,this.language):a}translateMessage(t,r,a){let n=this.language,s=n&&t[n],o=s&&s[r];return o&&(a?te(o,a):o)}};var A=i(l("piral-core")),S=e=>(0,A.defaultRender)(void 0);function z(e={}){let t=e.messages||{},r=Object.keys(t),a=r[0]||"en",n=e.language,o=(typeof n=="function"?n(r,a,"en"):n)||a;return new y(t,o,r.length?r:[o],e.fallback)}function re(e=z()){return t=>(t.defineActions(P(e)),t.dispatch(r=>({...r,components:{LanguagesPicker:S,...r.components},language:{loading:!1,available:e.languages,selected:e.language}})),r=>{let a={};return{addTranslations(n,s=!0){let o=n;s?o.unshift(e.messages):o.push(e.messages),this.setTranslations(v.all(o))},getCurrentLanguage(n){let s=t.readState(o=>o.language.selected);if(n){n(s);let o=f=>{n(f.currentLanguage)};return r.on("select-language",o),()=>r.off("select-language",o)}return s},setTranslations(n){a=n},getTranslations(){return a},translate(n,s){return e.localizeLocal(a,n,s)}}})}var m=i(l("piral-core"));function ae(e,t){let r=m.cookie.getItem("_culture")||m.storage.getItem("locale");return r||(t?t.toLowerCase().substring(0,2):navigator.language?navigator.language.substring(0,2):e)}function ne(e,t,r){let a=ae(t,r||"");return e.indexOf(a)!==-1?a:t}var b=i(l("react")),u=i(l("piral-core"));function se(e,t){let[r,a]=(0,b.useState)(e),{selectLanguage:n,setTranslations:s,getTranslations:o}=(0,u.useActions)();return(0,b.useEffect)(()=>{let f=!0,_=o(r);return n(void 0),t(r,_).then(d=>{f&&(s(r,d),n(r))},d=>console.error(d)),()=>{f=!1}},[r]),[r,a]}function oe(){let{translate:e}=(0,u.useActions)();return(0,u.useGlobalState)(t=>t.language.selected),e}var E=i(l("react")),C=i(l("piral-core"));var ie=()=>{let{available:e,selected:t}=(0,C.useGlobalState)(r=>r.language);return E.createElement(L,{selected:t,available:e})};return le;})();
1
+ var piralTranslate=(()=>{var R=Object.create;var m=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var $=Object.getPrototypeOf,I=Object.prototype.hasOwnProperty;var T=e=>m(e,"__esModule",{value:!0});var l=(e=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(e,{get:(t,r)=>(typeof require!="undefined"?require:t)[r]}):e)(function(e){if(typeof require!="undefined")return require.apply(this,arguments);throw new Error('Dynamic require of "'+e+'" is not supported')});var F=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),U=(e,t)=>{T(e);for(var r in t)m(e,r,{get:t[r],enumerable:!0})},D=(e,t,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of G(t))!I.call(e,a)&&a!=="default"&&m(e,a,{get:()=>t[a],enumerable:!(r=N(t,a))||r.enumerable});return e},i=e=>D(T(m(e!=null?R($(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var z=F((pe,x)=>{"use strict";var B=function(t){return V(t)&&!K(t)};function V(e){return!!e&&typeof e=="object"}function K(e){var t=Object.prototype.toString.call(e);return t==="[object RegExp]"||t==="[object Date]"||q(e)}var Y=typeof Symbol=="function"&&Symbol.for,Z=Y?Symbol.for("react.element"):60103;function q(e){return e.$$typeof===Z}function H(e){return Array.isArray(e)?[]:{}}function g(e,t){return t.clone!==!1&&t.isMergeableObject(e)?c(H(e),e,t):e}function J(e,t,r){return e.concat(t).map(function(a){return g(a,r)})}function Q(e,t){if(!t.customMerge)return c;var r=t.customMerge(e);return typeof r=="function"?r:c}function W(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(t){return Object.propertyIsEnumerable.call(e,t)}):[]}function O(e){return Object.keys(e).concat(W(e))}function h(e,t){try{return t in e}catch{return!1}}function X(e,t){return h(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))}function ee(e,t,r){var a={};return r.isMergeableObject(e)&&O(e).forEach(function(n){a[n]=g(e[n],r)}),O(t).forEach(function(n){X(e,n)||(h(e,n)&&r.isMergeableObject(t[n])?a[n]=Q(n,r)(e[n],t[n],r):a[n]=g(t[n],r))}),a}function c(e,t,r){r=r||{},r.arrayMerge=r.arrayMerge||J,r.isMergeableObject=r.isMergeableObject||B,r.cloneUnlessOtherwiseSpecified=g;var a=Array.isArray(t),n=Array.isArray(e),s=a===n;return s?a?r.arrayMerge(e,t,r):ee(e,t,r):g(t,r)}c.all=function(t,r){if(!Array.isArray(t))throw new Error("first argument should be an array");return t.reduce(function(a,n){return c(a,n,r)},{})};var te=c;x.exports=te});var ue={};U(ue,{Languages:()=>ge,PiralLanguagesPicker:()=>y,createLocaleApi:()=>se,getUserLocale:()=>ie,setupLocalizer:()=>C,useDynamicLanguage:()=>le,useTranslate:()=>ce});var j=i(l("piral-core")),y=(0,j.getPiralComponent)("LanguagesPicker");var E=i(z());function P(e){return{selectLanguage(t,r){t.dispatch(a=>{e.language=r;let n=a.language.selected,s=r;return setTimeout(()=>{t.emit("select-language",{previousLanguage:n,currentLanguage:s})},0),{...a,language:{...a.language,loading:r===void 0,selected:r}}})},translate(t,r,a){return e&&e.localizeGlobal(r,a)},setTranslations(t,r,a){e.messages[r]=a.global;for(let n of a.locals){let s=t.apis[n.name];if(s){let o=s.getTranslations();o[r]=n.value,s.setTranslations(o)}}},getTranslations(t,r){return{global:e.messages[r],locals:Object.keys(t.apis).map(a=>({name:a,value:t.apis[a].getTranslations()[r]}))}}}}function p(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,re(r)]))}function re(e){let t={};return A(e,t),t}function A(e,t,r=""){if(typeof e=="string"){t[r]=e;return}if(typeof e=="object"&&e!==null){Object.keys(e).forEach(a=>{A(e[a],t,r?`${r}.${a}`:a)});return}}function ae(e,t){return t?"...":""}function ne(e,t){return e.replace(/{{\s*([A-Za-z0-9_.]+)\s*}}/g,(r,a)=>a in t?t[a]||"":`{{${a}}}`)}var M=class{constructor(t,r,a,n=ae){this.language=r;this.languages=a;this.fallback=n;this.messages=p(t)}localizeGlobal(t,r){return this.localizeBase(t,r)}localizeLocal(t,r,a){let n=this.translateMessage(t,r,a);return n===void 0?this.localizeBase(r,a):n}localizeBase(t,r){let a=this.translateMessage(this.messages,t,r);return a===void 0?this.fallback(t,this.language):a}translateMessage(t,r,a){let n=this.language,s=n&&t[n],o=s&&s[r];return o&&(a?ne(o,a):o)}};var S=i(l("piral-core")),v=e=>(0,S.defaultRender)(void 0);function C(e={}){let t=e.messages||{},r=Object.keys(t),a=r[0]||"en",n=e.language,o=(typeof n=="function"?n(r,a,"en"):n)||a;return new M(t,o,r.length?r:[o],e.fallback)}function se(e=C()){return t=>(t.defineActions(P(e)),t.dispatch(r=>({...r,components:{LanguagesPicker:v,...r.components},language:{loading:!1,available:e.languages,selected:e.language}})),r=>{let a={};return{addTranslations(n,s=!0){let o=n;s?o.unshift(e.messages):o.push(e.messages),this.setTranslations(E.all(o))},getCurrentLanguage(n){let s=t.readState(o=>o.language.selected);if(n){n(s);let o=f=>{n(f.currentLanguage)};return r.on("select-language",o),()=>r.off("select-language",o)}return s},setTranslations(n){a=p(n)},getTranslations(){return a},translate(n,s){return e.localizeLocal(a,n,s)}}})}var b=i(l("piral-core"));function oe(e,t){let r=b.cookie.getItem("_culture")||b.storage.getItem("locale");return r||(t?t.toLowerCase().substring(0,2):navigator.language?navigator.language.substring(0,2):e)}function ie(e,t,r){let a=oe(t,r||"");return e.indexOf(a)!==-1?a:t}var d=i(l("react")),u=i(l("piral-core"));function le(e,t){let[r,a]=(0,d.useState)(e),{selectLanguage:n,setTranslations:s,getTranslations:o}=(0,u.useActions)();return(0,d.useEffect)(()=>{let f=!0,w=o(r);return n(void 0),t(r,w).then(L=>{f&&(s(r,L),n(r))},L=>console.error(L)),()=>{f=!1}},[r]),[r,a]}function ce(){let{translate:e}=(0,u.useActions)();return(0,u.useGlobalState)(t=>t.language.selected),e}var _=i(l("react")),k=i(l("piral-core"));var ge=()=>{let{available:e,selected:t}=(0,k.useGlobalState)(r=>r.language);return _.createElement(y,{selected:t,available:e})};return ue;})();
@@ -73,6 +73,22 @@ describe('Create Localize API', () => {
73
73
  expect(result).toEqual('bár');
74
74
  });
75
75
 
76
+ it('createApi can translate from local-global translations using the current language and passed nested translations', () => {
77
+ const config = {
78
+ language: 'en'
79
+ };
80
+ const api = (createLocaleApi(setupLocalizer(config))(context) as any)();
81
+ api.setTranslations({
82
+ en: {
83
+ header: {
84
+ title: 'Hello world'
85
+ }
86
+ }
87
+ });
88
+ const result = api.translate('header.title');
89
+ expect(result).toBe('Hello world');
90
+ });
91
+
76
92
  it('createApi falls back to standard string if language is not found', () => {
77
93
  const config = {
78
94
  language: 'en',
package/src/create.ts CHANGED
@@ -4,7 +4,8 @@ import type { PiralPlugin } from 'piral-core';
4
4
  import { createActions } from './actions';
5
5
  import { Localizer } from './localize';
6
6
  import { DefaultPicker } from './default';
7
- import { PiletLocaleApi, LocalizationMessages, Localizable, PiralSelectLanguageEvent } from './types';
7
+ import { PiletLocaleApi, LocalizationMessages, Localizable, PiralSelectLanguageEvent, NestedLocalizationMessages } from './types';
8
+ import { flattenTranslations } from './flatten-translations';
8
9
 
9
10
  export interface TranslationFallback {
10
11
  (key: string, language: string): string;
@@ -22,7 +23,7 @@ export interface LocaleConfig {
22
23
  * Sets the default (global) localization messages.
23
24
  * @default {}
24
25
  */
25
- messages?: LocalizationMessages;
26
+ messages?: LocalizationMessages | NestedLocalizationMessages;
26
27
  /**
27
28
  * Sets the default language to use.
28
29
  */
@@ -72,8 +73,8 @@ export function createLocaleApi(localizer: Localizable = setupLocalizer()): Pira
72
73
  let localTranslations: LocalizationMessages = {};
73
74
 
74
75
  return {
75
- addTranslations(messages: LocalizationMessages[], isOverriding: boolean = true) {
76
- const messagesToMerge: LocalizationMessages[] = messages;
76
+ addTranslations(messages, isOverriding = true) {
77
+ const messagesToMerge = messages;
77
78
 
78
79
  if (isOverriding) {
79
80
  messagesToMerge.unshift(localizer.messages);
@@ -100,7 +101,7 @@ export function createLocaleApi(localizer: Localizable = setupLocalizer()): Pira
100
101
  return selected;
101
102
  },
102
103
  setTranslations(messages) {
103
- localTranslations = messages;
104
+ localTranslations = flattenTranslations(messages);
104
105
  },
105
106
  getTranslations() {
106
107
  return localTranslations;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+ import { describe, it, expect } from 'vitest';
5
+ import { flattenTranslations } from './flatten-translations';
6
+
7
+ describe('Flatten translations', () => {
8
+ it('flattenTranslations can handle flat keys', () => {
9
+ const messages = {
10
+ en: {
11
+ key: 'value'
12
+ },
13
+ fr: {
14
+ key: 'value (fr)'
15
+ }
16
+ };
17
+ const flatMessages = flattenTranslations(messages);
18
+ expect(flatMessages.fr.key).toEqual('value (fr)');
19
+ });
20
+
21
+ it('flattenTranslations can handle flat dot keys', () => {
22
+ const messages = {
23
+ en: {
24
+ 'header.title': 'Hello world'
25
+ }
26
+ };
27
+ const flatMessages = flattenTranslations(messages);
28
+ expect(flatMessages.en['header.title']).toBe('Hello world');
29
+ });
30
+
31
+ it('flattenTranslations can handle nested keys', () => {
32
+ const messages = {
33
+ en: {
34
+ header: {
35
+ title: 'Hello world'
36
+ }
37
+ }
38
+ };
39
+ const flatMessages = flattenTranslations(messages);
40
+ expect(flatMessages.en['header.title']).toBe('Hello world');
41
+ });
42
+
43
+ it('flattenTranslations can handle nested keys with multiple depth levels', () => {
44
+ const messages = {
45
+ en: {
46
+ header: {
47
+ title: {
48
+ subtitle: 'Hello world'
49
+ }
50
+ }
51
+ }
52
+ };
53
+ const flatMessages = flattenTranslations(messages);
54
+ expect(flatMessages.en['header.title.subtitle']).toBe('Hello world');
55
+ });
56
+ });
@@ -0,0 +1,46 @@
1
+ import { LocalizationMessages, NestedLocalizationMessages } from './types';
2
+
3
+ export function flattenTranslations(messages: LocalizationMessages | NestedLocalizationMessages): LocalizationMessages {
4
+ return Object.fromEntries(
5
+ Object
6
+ .entries(messages)
7
+ .map(([ language, translations ]) => {
8
+ return [
9
+ language,
10
+ flat(translations)
11
+ ]
12
+ })
13
+ );
14
+ }
15
+
16
+ function flat(source: Record<string, unknown>): Record<string, string> {
17
+ const target: Record<string, string> = {};
18
+
19
+ flatten(source, target);
20
+
21
+ return target;
22
+ }
23
+
24
+ function flatten(source: any, target: Record<string, string>, prop = '') {
25
+ if (typeof source === 'string') {
26
+ target[prop] = source;
27
+
28
+ return;
29
+ }
30
+
31
+ if (typeof source === 'object' && source !== null) {
32
+ Object
33
+ .keys(source)
34
+ .forEach((key) => {
35
+ flatten(
36
+ source[key],
37
+ target,
38
+ prop
39
+ ? `${prop}.${key}`
40
+ : key
41
+ );
42
+ });
43
+
44
+ return;
45
+ }
46
+ }
@@ -8,6 +8,9 @@ const messages = {
8
8
  en: {
9
9
  hi: 'hello',
10
10
  greeting: 'Hi {{name}}, welcome back',
11
+ header: {
12
+ title: 'Hello world'
13
+ }
11
14
  },
12
15
  de: {
13
16
  hi: 'hallo',
@@ -76,4 +79,11 @@ describe('Localize Module', () => {
76
79
  const result = localizer.localizeGlobal('greeting', { name: undefined });
77
80
  expect(result).toBe('Hi , welcome back');
78
81
  });
82
+
83
+ it('localizeGlobal translates from global translations using passed nested translations', () => {
84
+ const localizer = new Localizer(messages, 'en');
85
+ const result = localizer.localizeGlobal('header.title');
86
+
87
+ expect(result).toBe('Hello world');
88
+ });
79
89
  });
package/src/localize.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { LocalizationMessages, Localizable } from './types';
1
+ import { LocalizationMessages, Localizable, NestedLocalizationMessages } from './types';
2
+ import { flattenTranslations } from './flatten-translations';
2
3
 
3
4
  function defaultFallback(key: string, language: string): string {
4
5
  if (process.env.NODE_ENV === 'production') {
@@ -20,15 +21,19 @@ function formatMessage<T extends object>(message: string, variables: T): string
20
21
  }
21
22
 
22
23
  export class Localizer implements Localizable {
24
+ public messages: LocalizationMessages;
25
+
23
26
  /**
24
27
  * Creates a new instance of a localizer.
25
28
  */
26
29
  constructor(
27
- public messages: LocalizationMessages,
30
+ messages: LocalizationMessages | NestedLocalizationMessages,
28
31
  public language: string,
29
32
  public languages: Array<string>,
30
33
  private fallback = defaultFallback,
31
- ) {}
34
+ ) {
35
+ this.messages = flattenTranslations(messages);
36
+ }
32
37
 
33
38
  /**
34
39
  * Localizes the given key via the global translations.
package/src/types.ts CHANGED
@@ -100,6 +100,13 @@ export interface Translations {
100
100
  [tag: string]: string;
101
101
  }
102
102
 
103
+ export interface NestedTranslations {
104
+ /**
105
+ * The available wordings (tag to translation or nested translations).
106
+ */
107
+ [tag: string]: string | NestedTranslations;
108
+ }
109
+
103
110
  export interface LanguageLoader {
104
111
  (language: string, current: LanguageData): Promise<LanguageData>;
105
112
  }
@@ -119,6 +126,13 @@ export interface LocalizationMessages {
119
126
  [lang: string]: Translations;
120
127
  }
121
128
 
129
+ export interface NestedLocalizationMessages {
130
+ /**
131
+ * The available languages (lang to wordings or nested wordings).
132
+ */
133
+ [lang: string]: NestedTranslations;
134
+ }
135
+
122
136
  export interface PiletLocaleApi {
123
137
  /**
124
138
  * Adds a list of translations to the existing translations.
@@ -129,7 +143,7 @@ export interface PiletLocaleApi {
129
143
  * @param messagesList The list of messages that extend the existing translations
130
144
  * @param [isOverriding=true] Indicates whether the new translations overwrite the existing translations
131
145
  */
132
- addTranslations(messagesList: LocalizationMessages[], isOverriding?: boolean): void;
146
+ addTranslations(messagesList: (LocalizationMessages | NestedLocalizationMessages)[], isOverriding?: boolean): void;
133
147
  /**
134
148
  * Gets the currently selected language directly.
135
149
  */
@@ -151,7 +165,7 @@ export interface PiletLocaleApi {
151
165
  * The translations will be exclusively used for retrieving translations for the pilet.
152
166
  * @param messages The messages to use as translation basis.
153
167
  */
154
- setTranslations(messages: LocalizationMessages): void;
168
+ setTranslations(messages: LocalizationMessages | NestedLocalizationMessages): void;
155
169
  /**
156
170
  * Gets the currently provided translations by the pilet.
157
171
  */