@noe-teritorio/opening_hours 3.14.1
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 +816 -0
- package/LICENSES/AGPL-3.0-only.txt +235 -0
- package/LICENSES/AGPL-3.0-or-later.txt +235 -0
- package/LICENSES/CC0-1.0.txt +121 -0
- package/LICENSES/LGPL-3.0-only.txt +304 -0
- package/LICENSES/ODbL-1.0.txt +540 -0
- package/Makefile +526 -0
- package/README.md +926 -0
- package/REUSE.toml +40 -0
- package/build/opening_hours.esm.mjs +45870 -0
- package/build/opening_hours.esm.mjs.map +1 -0
- package/build/opening_hours.js +45875 -0
- package/package.json +133 -0
- package/site/js/countryToLanguageMapping.js +247 -0
- package/site/js/helpers.js +735 -0
- package/site/js/i18n-resources.js +2284 -0
- package/site/js/main.js +401 -0
- package/site/js/opening_hours_table.js +414 -0
- package/site/js/theme.js +73 -0
- package/site/js/yohours_model.js +2791 -0
- package/src/locales/i18n.js +97 -0
- package/types/index.d.ts +159 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: © 2025 Kristjan ESPERANTO <https://github.com/KristjanESPERANTO>
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LGPL-3.0-only
|
|
5
|
+
*/
|
|
6
|
+
import resources from './translations.yaml';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Replace `{{varName}}` (or `{{-varName}}`) placeholders in a translation string.
|
|
10
|
+
* The `-` prefix is a legacy i18next no-HTML-escape marker; it has no effect here.
|
|
11
|
+
* @param {string} str - Translation string containing `{{…}}` placeholders.
|
|
12
|
+
* @param {object} vars - Map of placeholder names to replacement values.
|
|
13
|
+
* @returns {string} The interpolated translation string.
|
|
14
|
+
*/
|
|
15
|
+
function interpolate(str, vars) {
|
|
16
|
+
return str.replace(/{{-?([^{}]*)}}/g, function(match, varName) {
|
|
17
|
+
const name = varName.trim();
|
|
18
|
+
if (name in vars) {
|
|
19
|
+
return vars[name];
|
|
20
|
+
}
|
|
21
|
+
return match;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Extract the base language subtag from a locale tag (e.g. 'de-DE' → 'de').
|
|
27
|
+
*
|
|
28
|
+
* Accepts BCP 47 tags (e.g. 'de-DE') and POSIX identifiers per ISO 15897 (e.g. 'de_DE').
|
|
29
|
+
* For non-strings, returns 'en' (the default fallback locale).
|
|
30
|
+
* @param {string|null|undefined} locale - Locale tag.
|
|
31
|
+
* @returns {string} Base language, e.g. 'de'.
|
|
32
|
+
*/
|
|
33
|
+
function baseLanguage(locale) {
|
|
34
|
+
if (locale && typeof locale === 'string') {
|
|
35
|
+
return locale.split(/[-_]/)[0];
|
|
36
|
+
}
|
|
37
|
+
return 'en';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Build the locale fallback chain for a given locale tag.
|
|
42
|
+
*
|
|
43
|
+
* 'de-DE' → ['de-DE', 'de', 'en']
|
|
44
|
+
* 'de' → ['de', 'en']
|
|
45
|
+
* null → ['en']
|
|
46
|
+
* @param {string|null|undefined} locale - BCP 47 locale tag.
|
|
47
|
+
* @returns {string[]} Locale tags ordered from most to least specific.
|
|
48
|
+
*/
|
|
49
|
+
function localeChain(locale) {
|
|
50
|
+
const base = baseLanguage(locale);
|
|
51
|
+
// Deduplicate entries like ['de', 'de', 'en'] or ['en', 'en'].
|
|
52
|
+
return [...new Set([locale, base, 'en'].filter(Boolean))];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Walk the resource tree for the first locale in the fallback chain that has
|
|
57
|
+
* a translation for the given key.
|
|
58
|
+
*
|
|
59
|
+
* Tree shape: resources[locale][section][…key segments]
|
|
60
|
+
* @param {string|null|undefined} locale - BCP 47 locale tag.
|
|
61
|
+
* @param {string} section - 'texts' or 'pretty'.
|
|
62
|
+
* @param {string} key - Translation key (dot-separated for nesting).
|
|
63
|
+
* @returns {string|object|undefined} Matched value, or `undefined` if not found anywhere in the chain.
|
|
64
|
+
*/
|
|
65
|
+
function lookup(locale, section, key) {
|
|
66
|
+
const keyPath = key.split('.');
|
|
67
|
+
for (const loc of localeChain(locale)) {
|
|
68
|
+
let value = resources[loc]?.[section];
|
|
69
|
+
for (const segment of keyPath) value = value?.[segment];
|
|
70
|
+
// Return as soon as we find a value defined by the resource tree.
|
|
71
|
+
if (value !== undefined) return value;
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Translate a key into the requested locale, falling back through the locale
|
|
78
|
+
* chain to English. Returns the key itself when no translation is found.
|
|
79
|
+
* @param {string|null|undefined} locale - BCP 47 locale tag (e.g. 'de', 'de-DE').
|
|
80
|
+
* @param {string} section - 'texts' (error/warning messages) or
|
|
81
|
+
* 'pretty' (prettified output tokens).
|
|
82
|
+
* @param {string} key - Translation key (dot-separated for nesting).
|
|
83
|
+
* @param {object} [vars] - Variables to interpolate via `{{varName}}`.
|
|
84
|
+
* @returns {string} The translated string, or the key when no translation exists.
|
|
85
|
+
*/
|
|
86
|
+
export function translate(locale, section, key, vars) {
|
|
87
|
+
const result = lookup(locale, section, key);
|
|
88
|
+
|
|
89
|
+
if (typeof result === 'string') {
|
|
90
|
+
if (vars) {
|
|
91
|
+
return interpolate(result, vars);
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return key;
|
|
97
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
declare module 'opening_hours' {
|
|
2
|
+
export type opening_hours_warning_type =
|
|
3
|
+
| 'adding_0'
|
|
4
|
+
| 'additional_rule_separator_not_used_after_time_wrapping_midnight'
|
|
5
|
+
| 'additional_rule_which_evaluates_to_closed'
|
|
6
|
+
| 'ambiguous_word'
|
|
7
|
+
| 'combine_rules'
|
|
8
|
+
| 'default_state'
|
|
9
|
+
| 'empty_comment'
|
|
10
|
+
| 'hour_min_separator'
|
|
11
|
+
| 'interpreted_as_year'
|
|
12
|
+
| 'no_colon_after'
|
|
13
|
+
| 'nothing_useful'
|
|
14
|
+
| 'omit_ko'
|
|
15
|
+
| 'period_one'
|
|
16
|
+
| 'period_one_year_plus'
|
|
17
|
+
| 'please_use_ok_for_ko'
|
|
18
|
+
| 'public_holiday'
|
|
19
|
+
| 'rant_degree_sign_used_for_zero'
|
|
20
|
+
| 'separator_for_readability'
|
|
21
|
+
| 'strange_24_7'
|
|
22
|
+
| 'switched'
|
|
23
|
+
| 'use_multi'
|
|
24
|
+
| 'vague'
|
|
25
|
+
| 'value_ends_with_token'
|
|
26
|
+
| 'without_minutes'
|
|
27
|
+
| 'word_error_correction'
|
|
28
|
+
| 'year_past'
|
|
29
|
+
| 'zero_calculation'
|
|
30
|
+
|
|
31
|
+
export interface opening_hours_warning {
|
|
32
|
+
type: opening_hours_warning_type
|
|
33
|
+
message: string
|
|
34
|
+
/** The string the `position` offset refers to. This is the input value,
|
|
35
|
+
* except for selector-reordering warnings where it is the prettified value. */
|
|
36
|
+
value: string
|
|
37
|
+
/** Character offset into `value` where the warning points (the spot the
|
|
38
|
+
* `<--- ` marker is placed at in `getWarnings()`). `null` if it could not
|
|
39
|
+
* be determined. */
|
|
40
|
+
position: number | null
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface public_holiday_context {
|
|
44
|
+
isHoliday: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class opening_hours {
|
|
48
|
+
constructor(
|
|
49
|
+
value: string,
|
|
50
|
+
nominatim_object?: nominatim_object | null,
|
|
51
|
+
optional_conf_param?: optional_conf_param | null
|
|
52
|
+
)
|
|
53
|
+
getState(date?: Date): boolean
|
|
54
|
+
getUnknown(date?: Date): boolean
|
|
55
|
+
getStateString(
|
|
56
|
+
date: Date | undefined,
|
|
57
|
+
past: true
|
|
58
|
+
): 'open' | 'unknown' | 'closed'
|
|
59
|
+
getStateString(
|
|
60
|
+
date?: Date,
|
|
61
|
+
past?: false
|
|
62
|
+
): 'open' | 'unknown' | 'close'
|
|
63
|
+
getStateString(
|
|
64
|
+
date?: Date,
|
|
65
|
+
past?: boolean
|
|
66
|
+
): 'open' | 'unknown' | 'closed' | 'close'
|
|
67
|
+
getComment(date?: Date): string | undefined
|
|
68
|
+
getNextChange(date?: Date, maxdate?: Date): Date | undefined
|
|
69
|
+
getMatchingRule(date?: Date): number | undefined
|
|
70
|
+
getPublicHolidayContext(date?: Date): public_holiday_context
|
|
71
|
+
getOpenDuration(from: Date, to: Date): [number, number]
|
|
72
|
+
getOpenIntervals(
|
|
73
|
+
from: Date,
|
|
74
|
+
to: Date
|
|
75
|
+
): [Date, Date, boolean, string | undefined][]
|
|
76
|
+
getStatePair(
|
|
77
|
+
date?: Date
|
|
78
|
+
): [boolean, Date, boolean, string | undefined, number | undefined]
|
|
79
|
+
getWarnings(): string[]
|
|
80
|
+
getStructuredWarnings(): opening_hours_warning[]
|
|
81
|
+
isEqualTo(
|
|
82
|
+
second_oh_object: opening_hours,
|
|
83
|
+
start_date?: Date
|
|
84
|
+
): boolean
|
|
85
|
+
isWeekStable(): boolean
|
|
86
|
+
prettifyValue(argument_hash?: Partial<argument_hash>): string
|
|
87
|
+
getIterator(date?: Date): opening_hours_iterator
|
|
88
|
+
}
|
|
89
|
+
export default opening_hours
|
|
90
|
+
|
|
91
|
+
export class opening_hours_iterator {
|
|
92
|
+
getDate(): Date
|
|
93
|
+
setDate(date: Date): void
|
|
94
|
+
getState(date?: Date): boolean
|
|
95
|
+
getUnknown(date?: Date): boolean
|
|
96
|
+
getStateString(
|
|
97
|
+
date: Date | undefined,
|
|
98
|
+
past: true
|
|
99
|
+
): 'open' | 'unknown' | 'closed'
|
|
100
|
+
getStateString(
|
|
101
|
+
date?: Date,
|
|
102
|
+
past?: false
|
|
103
|
+
): 'open' | 'unknown' | 'close'
|
|
104
|
+
getStateString(
|
|
105
|
+
date?: Date,
|
|
106
|
+
past?: boolean
|
|
107
|
+
): 'open' | 'unknown' | 'closed' | 'close'
|
|
108
|
+
getComment(date?: Date): string | undefined
|
|
109
|
+
getMatchingRule(date?: Date): number | undefined
|
|
110
|
+
advance(limit?: Date): boolean
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface nominatim_object {
|
|
114
|
+
lat: number
|
|
115
|
+
lon: number
|
|
116
|
+
address: {
|
|
117
|
+
country_code: string
|
|
118
|
+
state: string
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface argument_hash {
|
|
123
|
+
rule_index: number | undefined
|
|
124
|
+
zero_pad_hour: boolean
|
|
125
|
+
one_zero_if_hour_zero: boolean
|
|
126
|
+
leave_off_closed: boolean
|
|
127
|
+
keyword_for_off_closed: string
|
|
128
|
+
rule_sep_string: string
|
|
129
|
+
print_semicolon: boolean
|
|
130
|
+
leave_weekday_sep_one_day_betw: boolean
|
|
131
|
+
sep_one_day_between: string
|
|
132
|
+
zero_pad_month_and_week_numbers: boolean
|
|
133
|
+
locale: string
|
|
134
|
+
date_format: Intl.DateTimeFormatOptions['weekday']
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export enum mode {
|
|
138
|
+
time_ranges = 0,
|
|
139
|
+
points_in_time = 1,
|
|
140
|
+
both = 2,
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export enum warnings_severity {
|
|
144
|
+
warning = 4,
|
|
145
|
+
notice = 5,
|
|
146
|
+
info = 6,
|
|
147
|
+
debug = 7,
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface optional_conf {
|
|
151
|
+
mode: mode | undefined
|
|
152
|
+
tag_key: string | undefined
|
|
153
|
+
map_value: boolean | undefined
|
|
154
|
+
warnings_severity: warnings_severity | undefined
|
|
155
|
+
locale: string | undefined
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export type optional_conf_param = number | optional_conf
|
|
159
|
+
}
|