@autobusal/providers 1.28.1 → 1.29.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 +32 -0
- package/Setup/Setup.tsx +5 -1
- package/Setup/languages.ts +42 -2
- package/package.json +1 -1
- package/types/settings.ts +20 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
## 1.29.0
|
|
5
|
+
|
|
6
|
+
### Changed
|
|
7
|
+
|
|
8
|
+
- **`getLanguage` takes the language the ORIGIN is about, and it outranks the
|
|
9
|
+
stored preference** — the only thing that does. The stored preference
|
|
10
|
+
exists so a returning visitor who last read the site in Albanian gets
|
|
11
|
+
Albanian at `busmagus.com/`, where the URL expresses no preference of its
|
|
12
|
+
own. On `busmagus.ro` the URL expresses nothing *but* a preference: the
|
|
13
|
+
domain is the request, and honouring a two-month-old `localStorage` entry
|
|
14
|
+
over it would render Albanian at a Romanian URL whose own canonical says it
|
|
15
|
+
is Romanian — reintroduced one returning visitor at a time, and invisible
|
|
16
|
+
to anybody testing in a clean browser.
|
|
17
|
+
|
|
18
|
+
It defaults to whatever `languages()` was told, so the two call sites that
|
|
19
|
+
ask outside of setup (the 500-error text in `apiClient`, the error page in
|
|
20
|
+
`Errors/Message`) answer in the language actually being read rather than
|
|
21
|
+
showing English error copy on a Romanian page.
|
|
22
|
+
|
|
23
|
+
Undefined — a single-domain brand, or an alias claiming no language —
|
|
24
|
+
leaves the ordering exactly as it was.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **`SettingsData.domain` / `.domains` / `.locale`** — which origin answered,
|
|
29
|
+
every origin the brand answers on, and the language this one is about.
|
|
30
|
+
`domains` is what turns hreflang from locale-to-path-prefix into
|
|
31
|
+
locale-to-**domain** (see `@autobusal/common`'s `localeHref`); its first
|
|
32
|
+
entry is the primary. All three optional, so an older API cannot break a
|
|
33
|
+
newer build.
|
|
34
|
+
|
|
3
35
|
## 1.28.1
|
|
4
36
|
|
|
5
37
|
### Fixed
|
package/Setup/Setup.tsx
CHANGED
|
@@ -15,7 +15,11 @@ const Setup = ({ type, children }: Props): JSX.Element => {
|
|
|
15
15
|
useGetMenu();
|
|
16
16
|
useUserBootstrap();
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
// Edited: Ferjolt Ozuni - Date: 2026-08-06
|
|
19
|
+
// `data.locale` - the language THIS origin is about, when it is a domain
|
|
20
|
+
// about a language (a ccTLD) rather than simply the brand's address. It
|
|
21
|
+
// outranks the stored preference; see getLanguage.
|
|
22
|
+
languages(type, data.preferences.languages.default, data.preferences.languages.available, data.locale);
|
|
19
23
|
|
|
20
24
|
// Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
21
25
|
// The brand's GTM container, from labels_settings via the admin GUI.
|
package/Setup/languages.ts
CHANGED
|
@@ -2,6 +2,13 @@ import i18next from 'i18next';
|
|
|
2
2
|
import Backend from 'i18next-http-backend';
|
|
3
3
|
import { initReactI18next } from 'react-i18next';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* The language this ORIGIN is about, remembered from the one place that is
|
|
7
|
+
* told it (`languages()`, from the settings payload) so the call sites that
|
|
8
|
+
* ask outside of setup do not each have to be handed it. See getLanguage.
|
|
9
|
+
*/
|
|
10
|
+
let originLocale: string | null | undefined;
|
|
11
|
+
|
|
5
12
|
/**
|
|
6
13
|
* The language to start in.
|
|
7
14
|
*
|
|
@@ -16,14 +23,42 @@ import { initReactI18next } from 'react-i18next';
|
|
|
16
23
|
* `available` is passed in rather than read from anywhere global so this
|
|
17
24
|
* stays a pure function of its inputs, and so an unrecognised first segment
|
|
18
25
|
* (/city/tirana) is never mistaken for a language.
|
|
26
|
+
*
|
|
27
|
+
* Edited: Ferjolt Ozuni - Date: 2026-08-06
|
|
28
|
+
* `domainLocale` - the language THIS origin is about, when it is about one
|
|
29
|
+
* (obtapi's settings payload, `locale`). It outranks the stored preference,
|
|
30
|
+
* which nothing else does.
|
|
31
|
+
*
|
|
32
|
+
* The stored preference exists so a returning visitor who last read the site
|
|
33
|
+
* in Albanian gets Albanian at busmagus.com/, where the URL expresses no
|
|
34
|
+
* preference of its own. On busmagus.ro the URL expresses nothing BUT a
|
|
35
|
+
* preference: the domain is the request, and honouring a two-month-old
|
|
36
|
+
* localStorage entry over it would render Albanian at a Romanian URL whose
|
|
37
|
+
* own canonical says it is Romanian - the mismatch localised URLs exist to
|
|
38
|
+
* remove, reintroduced one returning visitor at a time and invisible to
|
|
39
|
+
* anybody testing in a clean browser.
|
|
40
|
+
*
|
|
41
|
+
* Undefined (a single-domain brand, or an alias claiming no language) leaves
|
|
42
|
+
* the ordering exactly as it was.
|
|
43
|
+
*
|
|
44
|
+
* It DEFAULTS to whatever `languages()` was told, so the two call sites that
|
|
45
|
+
* ask this question outside of setup - the 500-error text in apiClient and
|
|
46
|
+
* the error page in Errors/Message, both of which pass only 'en' - answer in
|
|
47
|
+
* the language the visitor is actually reading rather than dropping back to
|
|
48
|
+
* a stale localStorage entry and showing English error copy on a Romanian
|
|
49
|
+
* page.
|
|
19
50
|
*/
|
|
20
|
-
export const getLanguage = (defaultLanguage: string, available: string[] = []): string => {
|
|
51
|
+
export const getLanguage = (defaultLanguage: string, available: string[] = [], domainLocale: string | null | undefined = originLocale): string => {
|
|
21
52
|
const [ , first ] = window.location.pathname.split('/');
|
|
22
53
|
|
|
23
54
|
if (first && available.includes(first)) {
|
|
24
55
|
return first;
|
|
25
56
|
}
|
|
26
57
|
|
|
58
|
+
if (domainLocale && (available.length === 0 || available.includes(domainLocale))) {
|
|
59
|
+
return domainLocale;
|
|
60
|
+
}
|
|
61
|
+
|
|
27
62
|
const stored = localStorage.getItem('language');
|
|
28
63
|
|
|
29
64
|
return (stored && (available.length === 0 || available.includes(stored)))
|
|
@@ -43,7 +78,12 @@ export const getLanguage = (defaultLanguage: string, available: string[] = []):
|
|
|
43
78
|
// consumer that hasn't set VITE_BUILD_ID yet (no worse than before).
|
|
44
79
|
const buildId = import.meta.env.VITE_BUILD_ID ?? 'dev';
|
|
45
80
|
|
|
46
|
-
const languages = (type: string, defaultLanguage: string, available: string[] = []): void => {
|
|
81
|
+
const languages = (type: string, defaultLanguage: string, available: string[] = [], domainLocale?: string | null): void => {
|
|
82
|
+
// Before the early return, not after: the guard is about not initialising
|
|
83
|
+
// i18next twice, and getLanguage's callers need this on every render of
|
|
84
|
+
// the app's life, not only the first one.
|
|
85
|
+
originLocale = domainLocale;
|
|
86
|
+
|
|
47
87
|
if (i18next.isInitialized) {
|
|
48
88
|
return;
|
|
49
89
|
}
|
package/package.json
CHANGED
package/types/settings.ts
CHANGED
|
@@ -7,6 +7,26 @@ export interface SettingsData {
|
|
|
7
7
|
|
|
8
8
|
url: string
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Edited: Ferjolt Ozuni - Date: 2026-08-06
|
|
12
|
+
* Multi-TLD: which origin answered this request, every origin this brand
|
|
13
|
+
* answers on, and the language this one is about.
|
|
14
|
+
*
|
|
15
|
+
* `domains` is what turns hreflang from locale-to-path-prefix into
|
|
16
|
+
* locale-to-DOMAIN (see @autobusal/common's localeHref). Its first entry
|
|
17
|
+
* is the primary - the origin registered with the payment gateways, and
|
|
18
|
+
* the one that hosts any language without a domain of its own under a
|
|
19
|
+
* /{locale}/ prefix.
|
|
20
|
+
*
|
|
21
|
+
* `locale` is null for a single-domain brand and for an alias that claims
|
|
22
|
+
* no language; everything derived from these then resolves to exactly the
|
|
23
|
+
* previous single-origin behaviour. All three are optional so an older API
|
|
24
|
+
* cannot break a newer build.
|
|
25
|
+
*/
|
|
26
|
+
domain?: string | null
|
|
27
|
+
domains?: { domain: string, locale?: string | null, primary?: boolean }[]
|
|
28
|
+
locale?: string | null
|
|
29
|
+
|
|
10
30
|
// Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
11
31
|
// Present ONLY while the brand is under construction - obtapi omits it
|
|
12
32
|
// entirely on a live site, so its presence is the switch itself and there
|