@twin.org/standards-unece 0.0.3-next.40 → 0.0.3-next.41

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.
@@ -17,6 +17,12 @@ export class UnCodeLists {
17
17
  * @internal
18
18
  */
19
19
  static _cache = {};
20
+ /**
21
+ * Static cache for code list labels per locale.
22
+ * Key format: `${locale}:${camelCaseCodeListName}:labels`
23
+ * @internal
24
+ */
25
+ static _labelsCache = {};
20
26
  /**
21
27
  * Get all the translations for a specific list type.
22
28
  * @param codeList The code list to get the translations for.
@@ -53,7 +59,7 @@ export class UnCodeLists {
53
59
  }
54
60
  const translations = {};
55
61
  for (const key in dictionary) {
56
- if (key.startsWith(codeListPrefix)) {
62
+ if (key.startsWith(codeListPrefix) && !key.endsWith("_label")) {
57
63
  const codeKey = key.slice(codeListPrefix.length);
58
64
  translations[codeKey] = dictionary[key];
59
65
  }
@@ -81,5 +87,67 @@ export class UnCodeLists {
81
87
  }
82
88
  return undefined;
83
89
  }
90
+ /**
91
+ * Get all the short description labels for a specific list type.
92
+ * Labels are stored in locale files with a `_label` suffix (e.g. `unece:arrivalEvent_label`).
93
+ * @param codeList The code list to get the labels for.
94
+ * @param locale The locale to get the labels for. If not provided, the default locale will be used. Falls back to 'en' if the locale doesn't exist.
95
+ * @returns The labels for the code list, keyed by the original code (without `_label` suffix).
96
+ */
97
+ static async getLabels(codeList, locale) {
98
+ Guards.stringValue(UnCodeLists.CLASS_NAME, "codeList", codeList);
99
+ const parts = codeList.split(":");
100
+ if (parts.length !== 2 || parts[0] !== "unece") {
101
+ throw new GeneralError(UnCodeLists.CLASS_NAME, "invalidCodeList", { codeList });
102
+ }
103
+ const finalLocale = locale ?? I18n.getLocale();
104
+ const camelCaseCodeList = StringHelper.camelCase(parts[1]);
105
+ const cacheKey = `${finalLocale}:${camelCaseCodeList}:labels`;
106
+ if (cacheKey in UnCodeLists._labelsCache) {
107
+ return UnCodeLists._labelsCache[cacheKey];
108
+ }
109
+ let dictionary = I18n.getDictionary(finalLocale);
110
+ let actualLocale = finalLocale;
111
+ const labelSuffix = "_label";
112
+ const codeListPrefix = `codeLists.${camelCaseCodeList}.`;
113
+ let hasTranslations = false;
114
+ for (const key in dictionary) {
115
+ if (key.startsWith(codeListPrefix) && key.endsWith(labelSuffix)) {
116
+ hasTranslations = true;
117
+ break;
118
+ }
119
+ }
120
+ if (!hasTranslations && finalLocale !== "en") {
121
+ dictionary = I18n.getDictionary("en");
122
+ actualLocale = "en";
123
+ }
124
+ const labels = {};
125
+ for (const key in dictionary) {
126
+ if (key.startsWith(codeListPrefix) && key.endsWith(labelSuffix)) {
127
+ const codeKey = key.slice(codeListPrefix.length, -labelSuffix.length);
128
+ labels[codeKey] = dictionary[key];
129
+ }
130
+ }
131
+ const actualCacheKey = `${actualLocale}:${camelCaseCodeList}:labels`;
132
+ UnCodeLists._labelsCache[actualCacheKey] = labels;
133
+ if (actualLocale !== finalLocale) {
134
+ UnCodeLists._labelsCache[cacheKey] = labels;
135
+ }
136
+ return labels;
137
+ }
138
+ /**
139
+ * Get a short description label for a specific code in a list type.
140
+ * @param codeList The code list to get the label for.
141
+ * @param key The key to get the label for.
142
+ * @param locale The locale to get the label for. If not provided, the default locale will be used.
143
+ * @returns The label for the specified key in the code list.
144
+ */
145
+ static async getLabel(codeList, key, locale) {
146
+ const labels = await UnCodeLists.getLabels(codeList, locale);
147
+ if (Is.object(labels) && Is.string(labels[key])) {
148
+ return labels[key];
149
+ }
150
+ return undefined;
151
+ }
84
152
  }
85
153
  //# sourceMappingURL=unCodeLists.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"unCodeLists.js","sourceRoot":"","sources":["../../../src/helpers/unCodeLists.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { GeneralError, Guards, I18n, Is, StringHelper } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { UneceCodeLists } from \"../models/uneceCodeLists.js\";\n\n/**\n * A class for handling Code Lists.\n * @see https://vocabulary.uncefact.org/code-lists\n */\nexport class UnCodeLists {\n\t/**\n\t * The class name.\n\t * @internal\n\t */\n\tpublic static readonly CLASS_NAME = nameof<UnCodeLists>();\n\n\t/**\n\t * Static cache for code list translations per locale.\n\t * Key format: `${locale}:${camelCaseCodeListName}`\n\t * @internal\n\t */\n\tprivate static readonly _cache: { [key: string]: { [key: string]: string } } = {};\n\n\t/**\n\t * Get all the translations for a specific list type.\n\t * @param codeList The code list to get the translations for.\n\t * @param locale The locale to get the translations for. If not provided, the default locale will be used. Falls back to 'en' if the locale doesn't exist.\n\t * @returns The translations for the code list.\n\t */\n\tpublic static async getDescriptions(\n\t\tcodeList: UneceCodeLists,\n\t\tlocale?: string\n\t): Promise<{\n\t\t[key: string]: string;\n\t}> {\n\t\tGuards.stringValue(UnCodeLists.CLASS_NAME, nameof(codeList), codeList);\n\n\t\tconst parts = codeList.split(\":\");\n\t\tif (parts.length !== 2 || parts[0] !== \"unece\") {\n\t\t\tthrow new GeneralError(UnCodeLists.CLASS_NAME, \"invalidCodeList\", { codeList });\n\t\t}\n\n\t\tconst finalLocale = locale ?? I18n.getLocale();\n\t\tconst camelCaseCodeList = StringHelper.camelCase(parts[1]);\n\t\tconst cacheKey = `${finalLocale}:${camelCaseCodeList}`;\n\n\t\t// Check if this code list is already cached\n\t\tif (cacheKey in UnCodeLists._cache) {\n\t\t\treturn UnCodeLists._cache[cacheKey];\n\t\t}\n\n\t\tlet dictionary = I18n.getDictionary(finalLocale);\n\t\tlet actualLocale = finalLocale;\n\t\tconst codeListPrefix = `codeLists.${camelCaseCodeList}.`;\n\n\t\t// If the requested locale is empty or doesn't have translations for this code list, fall back to 'en'\n\t\tlet hasTranslations = false;\n\t\tfor (const key in dictionary) {\n\t\t\tif (key.startsWith(codeListPrefix)) {\n\t\t\t\thasTranslations = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!hasTranslations && finalLocale !== \"en\") {\n\t\t\tdictionary = I18n.getDictionary(\"en\");\n\t\t\tactualLocale = \"en\";\n\t\t}\n\n\t\tconst translations: { [key: string]: string } = {};\n\t\tfor (const key in dictionary) {\n\t\t\tif (key.startsWith(codeListPrefix)) {\n\t\t\t\tconst codeKey = key.slice(codeListPrefix.length);\n\t\t\t\ttranslations[codeKey] = dictionary[key];\n\t\t\t}\n\t\t}\n\n\t\t// Cache under the actual locale used (accounting for fallback)\n\t\tconst actualCacheKey = `${actualLocale}:${camelCaseCodeList}`;\n\t\tUnCodeLists._cache[actualCacheKey] = translations;\n\n\t\t// Also cache under requested locale if it differs from actual locale (for faster fallback next time)\n\t\tif (actualLocale !== finalLocale) {\n\t\t\tUnCodeLists._cache[cacheKey] = translations;\n\t\t}\n\n\t\treturn translations;\n\t}\n\n\t/**\n\t * Get a translation for a specific list type.\n\t * @param codeList The code list to get the translations for.\n\t * @param key The key to get the translation for.\n\t * @param locale The locale to get the translations for. If not provided, the default locale will be used.\n\t * @returns The translation for the specified key in the code list.\n\t */\n\tpublic static async getDescription(\n\t\tcodeList: UneceCodeLists,\n\t\tkey: string,\n\t\tlocale?: string\n\t): Promise<string | undefined> {\n\t\tconst descriptions = await UnCodeLists.getDescriptions(codeList, locale);\n\n\t\tif (Is.object(descriptions) && Is.string(descriptions[key])) {\n\t\t\treturn descriptions[key];\n\t\t}\n\n\t\treturn undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"unCodeLists.js","sourceRoot":"","sources":["../../../src/helpers/unCodeLists.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { GeneralError, Guards, I18n, Is, StringHelper } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { UneceCodeLists } from \"../models/uneceCodeLists.js\";\n\n/**\n * A class for handling Code Lists.\n * @see https://vocabulary.uncefact.org/code-lists\n */\nexport class UnCodeLists {\n\t/**\n\t * The class name.\n\t * @internal\n\t */\n\tpublic static readonly CLASS_NAME = nameof<UnCodeLists>();\n\n\t/**\n\t * Static cache for code list translations per locale.\n\t * Key format: `${locale}:${camelCaseCodeListName}`\n\t * @internal\n\t */\n\tprivate static readonly _cache: { [key: string]: { [key: string]: string } } = {};\n\n\t/**\n\t * Static cache for code list labels per locale.\n\t * Key format: `${locale}:${camelCaseCodeListName}:labels`\n\t * @internal\n\t */\n\tprivate static readonly _labelsCache: { [key: string]: { [key: string]: string } } = {};\n\n\t/**\n\t * Get all the translations for a specific list type.\n\t * @param codeList The code list to get the translations for.\n\t * @param locale The locale to get the translations for. If not provided, the default locale will be used. Falls back to 'en' if the locale doesn't exist.\n\t * @returns The translations for the code list.\n\t */\n\tpublic static async getDescriptions(\n\t\tcodeList: UneceCodeLists,\n\t\tlocale?: string\n\t): Promise<{\n\t\t[key: string]: string;\n\t}> {\n\t\tGuards.stringValue(UnCodeLists.CLASS_NAME, nameof(codeList), codeList);\n\n\t\tconst parts = codeList.split(\":\");\n\t\tif (parts.length !== 2 || parts[0] !== \"unece\") {\n\t\t\tthrow new GeneralError(UnCodeLists.CLASS_NAME, \"invalidCodeList\", { codeList });\n\t\t}\n\n\t\tconst finalLocale = locale ?? I18n.getLocale();\n\t\tconst camelCaseCodeList = StringHelper.camelCase(parts[1]);\n\t\tconst cacheKey = `${finalLocale}:${camelCaseCodeList}`;\n\n\t\t// Check if this code list is already cached\n\t\tif (cacheKey in UnCodeLists._cache) {\n\t\t\treturn UnCodeLists._cache[cacheKey];\n\t\t}\n\n\t\tlet dictionary = I18n.getDictionary(finalLocale);\n\t\tlet actualLocale = finalLocale;\n\t\tconst codeListPrefix = `codeLists.${camelCaseCodeList}.`;\n\n\t\t// If the requested locale is empty or doesn't have translations for this code list, fall back to 'en'\n\t\tlet hasTranslations = false;\n\t\tfor (const key in dictionary) {\n\t\t\tif (key.startsWith(codeListPrefix)) {\n\t\t\t\thasTranslations = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!hasTranslations && finalLocale !== \"en\") {\n\t\t\tdictionary = I18n.getDictionary(\"en\");\n\t\t\tactualLocale = \"en\";\n\t\t}\n\n\t\tconst translations: { [key: string]: string } = {};\n\t\tfor (const key in dictionary) {\n\t\t\tif (key.startsWith(codeListPrefix) && !key.endsWith(\"_label\")) {\n\t\t\t\tconst codeKey = key.slice(codeListPrefix.length);\n\t\t\t\ttranslations[codeKey] = dictionary[key];\n\t\t\t}\n\t\t}\n\n\t\t// Cache under the actual locale used (accounting for fallback)\n\t\tconst actualCacheKey = `${actualLocale}:${camelCaseCodeList}`;\n\t\tUnCodeLists._cache[actualCacheKey] = translations;\n\n\t\t// Also cache under requested locale if it differs from actual locale (for faster fallback next time)\n\t\tif (actualLocale !== finalLocale) {\n\t\t\tUnCodeLists._cache[cacheKey] = translations;\n\t\t}\n\n\t\treturn translations;\n\t}\n\n\t/**\n\t * Get a translation for a specific list type.\n\t * @param codeList The code list to get the translations for.\n\t * @param key The key to get the translation for.\n\t * @param locale The locale to get the translations for. If not provided, the default locale will be used.\n\t * @returns The translation for the specified key in the code list.\n\t */\n\tpublic static async getDescription(\n\t\tcodeList: UneceCodeLists,\n\t\tkey: string,\n\t\tlocale?: string\n\t): Promise<string | undefined> {\n\t\tconst descriptions = await UnCodeLists.getDescriptions(codeList, locale);\n\n\t\tif (Is.object(descriptions) && Is.string(descriptions[key])) {\n\t\t\treturn descriptions[key];\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Get all the short description labels for a specific list type.\n\t * Labels are stored in locale files with a `_label` suffix (e.g. `unece:arrivalEvent_label`).\n\t * @param codeList The code list to get the labels for.\n\t * @param locale The locale to get the labels for. If not provided, the default locale will be used. Falls back to 'en' if the locale doesn't exist.\n\t * @returns The labels for the code list, keyed by the original code (without `_label` suffix).\n\t */\n\tpublic static async getLabels(\n\t\tcodeList: UneceCodeLists,\n\t\tlocale?: string\n\t): Promise<{\n\t\t[key: string]: string;\n\t}> {\n\t\tGuards.stringValue(UnCodeLists.CLASS_NAME, nameof(codeList), codeList);\n\n\t\tconst parts = codeList.split(\":\");\n\t\tif (parts.length !== 2 || parts[0] !== \"unece\") {\n\t\t\tthrow new GeneralError(UnCodeLists.CLASS_NAME, \"invalidCodeList\", { codeList });\n\t\t}\n\n\t\tconst finalLocale = locale ?? I18n.getLocale();\n\t\tconst camelCaseCodeList = StringHelper.camelCase(parts[1]);\n\t\tconst cacheKey = `${finalLocale}:${camelCaseCodeList}:labels`;\n\n\t\tif (cacheKey in UnCodeLists._labelsCache) {\n\t\t\treturn UnCodeLists._labelsCache[cacheKey];\n\t\t}\n\n\t\tlet dictionary = I18n.getDictionary(finalLocale);\n\t\tlet actualLocale = finalLocale;\n\t\tconst labelSuffix = \"_label\";\n\t\tconst codeListPrefix = `codeLists.${camelCaseCodeList}.`;\n\n\t\tlet hasTranslations = false;\n\t\tfor (const key in dictionary) {\n\t\t\tif (key.startsWith(codeListPrefix) && key.endsWith(labelSuffix)) {\n\t\t\t\thasTranslations = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!hasTranslations && finalLocale !== \"en\") {\n\t\t\tdictionary = I18n.getDictionary(\"en\");\n\t\t\tactualLocale = \"en\";\n\t\t}\n\n\t\tconst labels: { [key: string]: string } = {};\n\t\tfor (const key in dictionary) {\n\t\t\tif (key.startsWith(codeListPrefix) && key.endsWith(labelSuffix)) {\n\t\t\t\tconst codeKey = key.slice(codeListPrefix.length, -labelSuffix.length);\n\t\t\t\tlabels[codeKey] = dictionary[key];\n\t\t\t}\n\t\t}\n\n\t\tconst actualCacheKey = `${actualLocale}:${camelCaseCodeList}:labels`;\n\t\tUnCodeLists._labelsCache[actualCacheKey] = labels;\n\n\t\tif (actualLocale !== finalLocale) {\n\t\t\tUnCodeLists._labelsCache[cacheKey] = labels;\n\t\t}\n\n\t\treturn labels;\n\t}\n\n\t/**\n\t * Get a short description label for a specific code in a list type.\n\t * @param codeList The code list to get the label for.\n\t * @param key The key to get the label for.\n\t * @param locale The locale to get the label for. If not provided, the default locale will be used.\n\t * @returns The label for the specified key in the code list.\n\t */\n\tpublic static async getLabel(\n\t\tcodeList: UneceCodeLists,\n\t\tkey: string,\n\t\tlocale?: string\n\t): Promise<string | undefined> {\n\t\tconst labels = await UnCodeLists.getLabels(codeList, locale);\n\n\t\tif (Is.object(labels) && Is.string(labels[key])) {\n\t\t\treturn labels[key];\n\t\t}\n\n\t\treturn undefined;\n\t}\n}\n"]}