@geogirafe/lib-geoportal 1.0.2214756202 → 1.0.2217896135

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/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "GeoGirafe PSC",
6
6
  "url": "https://doc.geomapfish.dev"
7
7
  },
8
- "version": "1.0.2214756202",
8
+ "version": "1.0.2217896135",
9
9
  "type": "module",
10
10
  "engines": {
11
11
  "node": ">=20.19.0"
@@ -1 +1 @@
1
- {"version":"1.0.2214756202", "build":"2214756202", "date":"15/12/2025"}
1
+ {"version":"1.0.2217896135", "build":"2217896135", "date":"16/12/2025"}
@@ -11,7 +11,8 @@ export type TranslationsDict = {
11
11
  [lang: string]: string;
12
12
  };
13
13
  declare class I18nManager extends GirafeSingleton {
14
- private translations;
14
+ private readonly translations;
15
+ private readonly translationAliases;
15
16
  private loadingLanguagePromise;
16
17
  constructor(context: IGirafeContext);
17
18
  initializeSingleton(): void;
@@ -22,5 +23,11 @@ declare class I18nManager extends GirafeSingleton {
22
23
  translate(dom: DocumentFragment | HTMLElement): Promise<void>;
23
24
  private handleLanguageChange;
24
25
  private getFnTranslated;
26
+ /**
27
+ * Define a translation alias.
28
+ * The alias will use the same translation as the key.
29
+ * But if the key already has another translation, the alias will be ignored
30
+ */
31
+ addTranslationAlias(key: string, alias: string): void;
25
32
  }
26
33
  export default I18nManager;
@@ -1,6 +1,7 @@
1
1
  import GirafeSingleton from '../../base/GirafeSingleton';
2
2
  class I18nManager extends GirafeSingleton {
3
3
  translations = {};
4
+ translationAliases = {};
4
5
  loadingLanguagePromise = null;
5
6
  constructor(context) {
6
7
  super(context);
@@ -34,7 +35,7 @@ class I18nManager extends GirafeSingleton {
34
35
  if (language in this.translations) {
35
36
  // Translation were already loaded.
36
37
  // => stop here
37
- return Promise.resolve(this.translations[language]);
38
+ return this.translations[language];
38
39
  }
39
40
  // Load translations
40
41
  this.loadingLanguagePromise = this.context.configManager.loadConfig().then(async () => {
@@ -61,10 +62,20 @@ class I18nManager extends GirafeSingleton {
61
62
  getTranslation(key) {
62
63
  const currentLanguage = this.context.stateManager?.state?.language ?? 'en';
63
64
  const translationDict = this.translations[currentLanguage];
64
- const translation = translationDict ? translationDict[key] : null;
65
- if (translation !== undefined && translation !== null) {
66
- return translation;
65
+ if (translationDict) {
66
+ // First look in translations
67
+ let translation = translationDict[key];
68
+ if (translation) {
69
+ return translation;
70
+ }
71
+ // Otherwise, try with translation alias
72
+ const alias = this.translationAliases[key];
73
+ translation = translationDict[alias];
74
+ if (translation) {
75
+ return translation;
76
+ }
67
77
  }
78
+ // No translation found.
68
79
  return key;
69
80
  }
70
81
  async translate(dom) {
@@ -73,7 +84,7 @@ class I18nManager extends GirafeSingleton {
73
84
  return;
74
85
  }
75
86
  const toTranslate = dom.querySelectorAll('[i18n]');
76
- toTranslate.forEach((item) => {
87
+ for (const item of toTranslate) {
77
88
  const key = item.getAttribute('i18n');
78
89
  let translation;
79
90
  if (item.hasAttribute('i18nFn')) {
@@ -89,13 +100,13 @@ class I18nManager extends GirafeSingleton {
89
100
  // Default : simply set innerHTML.
90
101
  item.innerHTML = translation;
91
102
  }
92
- });
103
+ }
93
104
  const tooltips = dom.querySelectorAll('[tip]');
94
- tooltips.forEach((item) => {
105
+ for (const item of tooltips) {
95
106
  const key = item.getAttribute('tip');
96
107
  const translation = this.getTranslation(key);
97
108
  item.setAttribute('title', translation);
98
- });
109
+ }
99
110
  }
100
111
  handleLanguageChange() {
101
112
  const newLanguage = this.context.stateManager.state.language;
@@ -114,5 +125,15 @@ class I18nManager extends GirafeSingleton {
114
125
  }
115
126
  return key;
116
127
  }
128
+ /**
129
+ * Define a translation alias.
130
+ * The alias will use the same translation as the key.
131
+ * But if the key already has another translation, the alias will be ignored
132
+ */
133
+ addTranslationAlias(key, alias) {
134
+ if (key !== alias) {
135
+ this.translationAliases[alias] = key;
136
+ }
137
+ }
117
138
  }
118
139
  export default I18nManager;
@@ -14,7 +14,7 @@ describe('I18nManager.loadTranslations', () => {
14
14
  i18nManager.loadingLanguagePromise = null;
15
15
  configManager = context.configManager;
16
16
  configManager.Config.languages.translations = {};
17
- global.fetch = fetchMock;
17
+ globalThis.fetch = fetchMock;
18
18
  });
19
19
  afterAll(() => {
20
20
  MockHelper.stopMocking(context);
@@ -134,6 +134,13 @@ describe('I18nManager.getTranslation', () => {
134
134
  const translation = i18nManager.getTranslation('unknownKey');
135
135
  expect(translation).toBe('unknownKey');
136
136
  });
137
+ it('should return translation of the key if alias is given', () => {
138
+ // Set current language to French (where 'unknownKey' does not exist)
139
+ stateManager.state.language = 'fr';
140
+ i18nManager.addTranslationAlias('layer', 'layerAlias');
141
+ const translation = i18nManager.getTranslation('layerAlias');
142
+ expect(translation).toBe('couche');
143
+ });
137
144
  });
138
145
  describe('I18nManager.translate', () => {
139
146
  let i18nManager;
@@ -25,7 +25,7 @@ export default class OnBoardingManager extends GirafeSingleton {
25
25
  progressText: this.context.i18nManager.getTranslation('onboarding-progress-text')
26
26
  });
27
27
  const steps = [];
28
- for (const stepConfig of this.config.onboarding.steps) {
28
+ for (const stepConfig of this.config.onboarding.steps ?? []) {
29
29
  let element;
30
30
  if (stepConfig.component) {
31
31
  // @ts-expect-error getChildElement is protected, but we do not want to make it public,
@@ -324,7 +324,13 @@ class ThemesManager extends GirafeSingleton {
324
324
  if (options.metadata?.metadataUrl) {
325
325
  options.metadata.metadataUrl = this.calculateMetadataUrl(options.metadata.metadataUrl);
326
326
  }
327
- return new LayerWms(elem.id, elem.name, order.value, ogcServer, elem);
327
+ const wmsLayer = new LayerWms(elem.id, elem.name, order.value, ogcServer, elem);
328
+ // For WMFS queries, the layers attribute will be used. It can be different from the name.
329
+ // But in order to be able to define the translations only once, we use an translation alias here.
330
+ if (wmsLayer.layers) {
331
+ this.context.i18nManager.addTranslationAlias(wmsLayer.name, wmsLayer.layers);
332
+ }
333
+ return wmsLayer;
328
334
  }
329
335
  else {
330
336
  // Layer is invalid : it does not have any OGC-Server
@@ -10,7 +10,7 @@ const emptyTheme = {
10
10
  };
11
11
  beforeAll(async () => {
12
12
  context = MockHelper.startMocking();
13
- global.fetch = fetchMock;
13
+ globalThis.fetch = fetchMock;
14
14
  fetchMock.mockResolvedValueOnce({ json: vi.fn().mockResolvedValue(emptyTheme) });
15
15
  manager = context.themesManager;
16
16
  // @ts-ignore