@prezly/theme-kit-nextjs 3.2.3-0 → 3.2.3-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/build/components-nextjs/PageSeo/PageSeo.js +7 -1
- package/build/components-nextjs/PageSeo/PageSeo.js.map +1 -1
- package/build/intl/getFallbackLocale.d.ts +5 -3
- package/build/intl/getFallbackLocale.js +10 -7
- package/build/intl/getFallbackLocale.js.map +1 -1
- package/build/intl/locale.d.ts +3 -9
- package/build/intl/localeObject.d.ts +3 -3
- package/build/intl/localeObject.js +5 -5
- package/build/intl/localeObject.js.map +1 -1
- package/build/seo/getAlternateLanguageLinks.d.ts +1 -1
- package/build/seo/getAlternateLanguageLinks.js +72 -37
- package/build/seo/getAlternateLanguageLinks.js.map +1 -1
- package/build/seo/utils/bindLanguagesWithLocales.d.ts +11 -0
- package/build/seo/utils/bindLanguagesWithLocales.js +23 -0
- package/build/seo/utils/bindLanguagesWithLocales.js.map +1 -0
- package/build/seo/utils/createAlternateLanguageLink.d.ts +1 -1
- package/build/seo/utils/createAlternateLanguageLink.js +3 -3
- package/build/seo/utils/createAlternateLanguageLink.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/components-nextjs/PageSeo/PageSeo.tsx +13 -10
- package/src/intl/getFallbackLocale.ts +8 -5
- package/src/intl/locale.ts +3 -3
- package/src/intl/localeObject.ts +5 -5
- package/src/seo/getAlternateLanguageLinks.test.ts +37 -23
- package/src/seo/getAlternateLanguageLinks.ts +90 -47
- package/src/seo/utils/bindLanguagesWithLocales.ts +31 -0
- package/src/seo/utils/createAlternateLanguageLink.ts +3 -4
- package/build/seo/utils/getDefaultHrefLang.d.ts +0 -11
- package/build/seo/utils/getDefaultHrefLang.js +0 -28
- package/build/seo/utils/getDefaultHrefLang.js.map +0 -1
- package/build/seo/utils/mapLanguagesToLocales.d.ts +0 -4
- package/build/seo/utils/mapLanguagesToLocales.js +0 -24
- package/build/seo/utils/mapLanguagesToLocales.js.map +0 -1
- package/src/seo/utils/getDefaultHrefLang.ts +0 -57
- package/src/seo/utils/mapLanguagesToLocales.ts +0 -28
package/package.json
CHANGED
|
@@ -68,16 +68,19 @@ export function PageSeo({
|
|
|
68
68
|
|
|
69
69
|
const usedLanguages = getUsedLanguages(languages);
|
|
70
70
|
|
|
71
|
-
return getAlternateLanguageLinks(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
71
|
+
return getAlternateLanguageLinks(usedLanguages, (locale) => {
|
|
72
|
+
const translationUrl = getTranslationUrl(locale);
|
|
73
|
+
|
|
74
|
+
if (!translationUrl) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return getAbsoluteUrl(
|
|
79
|
+
translationUrl,
|
|
80
|
+
site.url,
|
|
81
|
+
currentStory && translationUrl !== '/' ? false : getLinkLocaleSlug(locale),
|
|
82
|
+
);
|
|
83
|
+
});
|
|
81
84
|
}, [currentStory, getLinkLocaleSlug, getTranslationUrl, languages, site.url]);
|
|
82
85
|
|
|
83
86
|
return (
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import type { LangCode } from './locale';
|
|
2
2
|
import { LocaleObject } from './localeObject';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
* Fallback locales for each language.
|
|
6
|
-
* For example, a story has no en(global) locale, then we can take some fallback locale from here.
|
|
7
|
-
*/
|
|
8
|
-
export const localeFallback: Record<LangCode, LocaleObject[]> = {
|
|
4
|
+
const localeFallback: Record<LangCode, LocaleObject[]> = {
|
|
9
5
|
en: [LocaleObject.fromAnyCode('en-US'), LocaleObject.fromAnyCode('en-GB')],
|
|
10
6
|
fr: [LocaleObject.fromAnyCode('fr-FR'), LocaleObject.fromAnyCode('fr-CA')],
|
|
11
7
|
};
|
|
12
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Fallback locales for each region independent locale.
|
|
11
|
+
* For example, a story has en-CA en-AU and en-GB locales. As you can see there is no region independent locale.
|
|
12
|
+
* We will use a list of possible fallbacks to determine region independent locale alias.
|
|
13
|
+
* In the provided example the result will be en-GB since it is defined in the localeFallback list
|
|
14
|
+
* If the list will be en-CA en-AU and en-US then the result will be en-US since it is the first one and hence takes precedence.
|
|
15
|
+
*/
|
|
13
16
|
export function getFallbackLocale(
|
|
14
17
|
langCode: LangCode,
|
|
15
18
|
availableLocales: LocaleObject[],
|
package/src/intl/locale.ts
CHANGED
|
@@ -8,9 +8,9 @@ export const DEFAULT_LOCALE = 'en';
|
|
|
8
8
|
// We use pseudo locale used for localization testing, to reliably determine if we need to fallback to the default newsroom language
|
|
9
9
|
export const DUMMY_DEFAULT_LOCALE = 'qps-ploc';
|
|
10
10
|
|
|
11
|
-
export type LangCode = string
|
|
12
|
-
export type RegionCode = string
|
|
13
|
-
export type LocaleCode = string
|
|
11
|
+
export type LangCode = string;
|
|
12
|
+
export type RegionCode = string;
|
|
13
|
+
export type LocaleCode = string;
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* This a list of locales that Prezly has translations for. Each code represents a language file in the `@prezly/themes-intl-messages` package.
|
package/src/intl/localeObject.ts
CHANGED
|
@@ -13,10 +13,10 @@ export class LocaleObject {
|
|
|
13
13
|
private localeCode: string;
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* Whether the locale is
|
|
17
|
-
* I.E. `en` is
|
|
16
|
+
* Whether the locale is region independent (without region/culture part).
|
|
17
|
+
* I.E. `en` is region independent, while `en-US` is not.
|
|
18
18
|
*/
|
|
19
|
-
public
|
|
19
|
+
public isRegionIndependent: boolean;
|
|
20
20
|
|
|
21
21
|
private constructor(localeCode: string) {
|
|
22
22
|
if (!/^([a-z]{2,3})(-[a-z\d]{1,4})?$/i.test(localeCode)) {
|
|
@@ -26,13 +26,13 @@ export class LocaleObject {
|
|
|
26
26
|
const [language, region] = localeCode.split('-');
|
|
27
27
|
|
|
28
28
|
if (region) {
|
|
29
|
-
this.
|
|
29
|
+
this.isRegionIndependent = false;
|
|
30
30
|
// Workaround for `zh-Hant` locale, which is the only locale with non-uppercase region part
|
|
31
31
|
const regionSuffix = region === 'hant' ? 'Hant' : region.toUpperCase();
|
|
32
32
|
|
|
33
33
|
this.localeCode = [language, regionSuffix].join('-');
|
|
34
34
|
} else {
|
|
35
|
-
this.
|
|
35
|
+
this.isRegionIndependent = true;
|
|
36
36
|
this.localeCode = language;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -10,13 +10,15 @@ function getTranslationUrl(locale: LocaleObject) {
|
|
|
10
10
|
return `translationUrl/${locale.toHyphenCode()}`;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
function
|
|
13
|
+
function generateTranslationUrl(locale: LocaleObject) {
|
|
14
|
+
const translationUrl = getTranslationUrl(locale);
|
|
15
|
+
|
|
14
16
|
return `http://localhost:3000/${locale.toNeutralLanguageCode()}/${translationUrl}`;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
describe('getAlternateLanguageLinks', () => {
|
|
18
20
|
it('should handle one en-GB non-default language', () => {
|
|
19
|
-
const links = getAlternateLanguageLinks([lang('en-GB')],
|
|
21
|
+
const links = getAlternateLanguageLinks([lang('en-GB')], generateTranslationUrl);
|
|
20
22
|
|
|
21
23
|
expect(links).toMatchObject([
|
|
22
24
|
{ href: 'http://localhost:3000/en/translationUrl/en-GB', hrefLang: 'en' },
|
|
@@ -26,11 +28,7 @@ describe('getAlternateLanguageLinks', () => {
|
|
|
26
28
|
});
|
|
27
29
|
|
|
28
30
|
it('should handle one en-GB default language', () => {
|
|
29
|
-
const links = getAlternateLanguageLinks(
|
|
30
|
-
[lang('en-GB', true)],
|
|
31
|
-
getTranslationUrl,
|
|
32
|
-
createHref,
|
|
33
|
-
);
|
|
31
|
+
const links = getAlternateLanguageLinks([lang('en-GB', true)], generateTranslationUrl);
|
|
34
32
|
|
|
35
33
|
expect(links).toMatchObject([
|
|
36
34
|
{ href: 'http://localhost:3000/en/translationUrl/en-GB', hrefLang: 'en' },
|
|
@@ -42,8 +40,7 @@ describe('getAlternateLanguageLinks', () => {
|
|
|
42
40
|
it('should handle two full locales', () => {
|
|
43
41
|
const links = getAlternateLanguageLinks(
|
|
44
42
|
[lang('en-GB', true), lang('fr-FR')],
|
|
45
|
-
|
|
46
|
-
createHref,
|
|
43
|
+
generateTranslationUrl,
|
|
47
44
|
);
|
|
48
45
|
|
|
49
46
|
expect(links).toMatchObject([
|
|
@@ -58,8 +55,7 @@ describe('getAlternateLanguageLinks', () => {
|
|
|
58
55
|
it('should use en-GB locale as x-default even if other locale is set as default', () => {
|
|
59
56
|
const links = getAlternateLanguageLinks(
|
|
60
57
|
[lang('en-GB'), lang('fr-FR', true)],
|
|
61
|
-
|
|
62
|
-
createHref,
|
|
58
|
+
generateTranslationUrl,
|
|
63
59
|
);
|
|
64
60
|
|
|
65
61
|
expect(links).toMatchObject([
|
|
@@ -74,8 +70,7 @@ describe('getAlternateLanguageLinks', () => {
|
|
|
74
70
|
it('should use default locale as x-default when there is eng locale', () => {
|
|
75
71
|
const links = getAlternateLanguageLinks(
|
|
76
72
|
[lang('ru-RU'), lang('fr-FR', true)],
|
|
77
|
-
|
|
78
|
-
createHref,
|
|
73
|
+
generateTranslationUrl,
|
|
79
74
|
);
|
|
80
75
|
|
|
81
76
|
expect(links).toMatchObject([
|
|
@@ -87,11 +82,10 @@ describe('getAlternateLanguageLinks', () => {
|
|
|
87
82
|
]);
|
|
88
83
|
});
|
|
89
84
|
|
|
90
|
-
it('should include provided
|
|
85
|
+
it('should include provided region independent locale', () => {
|
|
91
86
|
const links = getAlternateLanguageLinks(
|
|
92
87
|
[lang('en-US'), lang('fr'), lang('fr-FR', true)],
|
|
93
|
-
|
|
94
|
-
createHref,
|
|
88
|
+
generateTranslationUrl,
|
|
95
89
|
);
|
|
96
90
|
|
|
97
91
|
expect(links).toMatchObject([
|
|
@@ -103,11 +97,10 @@ describe('getAlternateLanguageLinks', () => {
|
|
|
103
97
|
]);
|
|
104
98
|
});
|
|
105
99
|
|
|
106
|
-
it('should use provided en
|
|
100
|
+
it('should use provided en region independent locale as x-default', () => {
|
|
107
101
|
const links = getAlternateLanguageLinks(
|
|
108
102
|
[lang('en'), lang('en-US'), lang('fr'), lang('fr-FR')],
|
|
109
|
-
|
|
110
|
-
createHref,
|
|
103
|
+
generateTranslationUrl,
|
|
111
104
|
);
|
|
112
105
|
|
|
113
106
|
expect(links).toMatchObject([
|
|
@@ -122,8 +115,7 @@ describe('getAlternateLanguageLinks', () => {
|
|
|
122
115
|
it('should fallback en link to en-US locale when there is en-GB locale', () => {
|
|
123
116
|
const links = getAlternateLanguageLinks(
|
|
124
117
|
[lang('en-GB'), lang('en-US')],
|
|
125
|
-
|
|
126
|
-
createHref,
|
|
118
|
+
generateTranslationUrl,
|
|
127
119
|
);
|
|
128
120
|
|
|
129
121
|
expect(links).toMatchObject([
|
|
@@ -137,8 +129,16 @@ describe('getAlternateLanguageLinks', () => {
|
|
|
137
129
|
it('should should omit locales if getTranslationUrl is undefined', () => {
|
|
138
130
|
const links = getAlternateLanguageLinks(
|
|
139
131
|
[lang('en-US'), lang('fr'), lang('fr-FR', true)],
|
|
140
|
-
(locale) =>
|
|
141
|
-
|
|
132
|
+
(locale) => {
|
|
133
|
+
const translationUrl =
|
|
134
|
+
locale.toHyphenCode() === 'en-US' ? undefined : getTranslationUrl(locale);
|
|
135
|
+
|
|
136
|
+
if (translationUrl) {
|
|
137
|
+
return generateTranslationUrl(locale);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return undefined;
|
|
141
|
+
},
|
|
142
142
|
);
|
|
143
143
|
|
|
144
144
|
expect(links).toMatchObject([
|
|
@@ -147,4 +147,18 @@ describe('getAlternateLanguageLinks', () => {
|
|
|
147
147
|
{ href: 'http://localhost:3000/fr/translationUrl/fr-FR', hrefLang: 'x-default' },
|
|
148
148
|
]);
|
|
149
149
|
});
|
|
150
|
+
|
|
151
|
+
it('should should not duplicate links when equal languages passed', () => {
|
|
152
|
+
const links = getAlternateLanguageLinks(
|
|
153
|
+
[lang('en-GB'), lang('en-GB'), lang('en-US'), lang('en-US')],
|
|
154
|
+
generateTranslationUrl,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
expect(links).toMatchObject([
|
|
158
|
+
{ href: 'http://localhost:3000/en/translationUrl/en-US', hrefLang: 'en' },
|
|
159
|
+
{ href: 'http://localhost:3000/en/translationUrl/en-GB', hrefLang: 'en-GB' },
|
|
160
|
+
{ href: 'http://localhost:3000/en/translationUrl/en-US', hrefLang: 'en-US' },
|
|
161
|
+
{ href: 'http://localhost:3000/en/translationUrl/en-US', hrefLang: 'x-default' },
|
|
162
|
+
]);
|
|
163
|
+
});
|
|
150
164
|
});
|
|
@@ -4,69 +4,112 @@ import type { AlternateLanguageLink } from '../components-nextjs/PageSeo';
|
|
|
4
4
|
import type { LocaleObject } from '../intl';
|
|
5
5
|
import { getFallbackLocale } from '../intl';
|
|
6
6
|
|
|
7
|
+
import { bindLanguagesWithLocales } from './utils/bindLanguagesWithLocales';
|
|
7
8
|
import { createAlternateLanguageLink } from './utils/createAlternateLanguageLink';
|
|
8
|
-
import { getDefaultHrefLang } from './utils/getDefaultHrefLang';
|
|
9
|
-
import { mapLanguagesToLocales } from './utils/mapLanguagesToLocales';
|
|
10
9
|
|
|
11
10
|
export function getAlternateLanguageLinks(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
createHref: (locale: LocaleObject, translationUrl: string) => string,
|
|
11
|
+
availableLanguages: NewsroomLanguageSettings[],
|
|
12
|
+
generateTranslationUrl: (locale: LocaleObject) => string | undefined,
|
|
15
13
|
): AlternateLanguageLink[] {
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const [localesByLangCode, defaultLangLocale] = mapLanguagesToLocales(languages);
|
|
14
|
+
const languagesWithLocales = bindLanguagesWithLocales(availableLanguages);
|
|
15
|
+
const hrefLangLinks: Array<AlternateLanguageLink> = [];
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
function pushLocaleToLinks(locale: LocaleObject, hrefLang?: string) {
|
|
18
|
+
const link = createAlternateLanguageLink(locale, generateTranslationUrl);
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
if (!link) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (hrefLang) {
|
|
25
|
+
hrefLangLinks.push({ ...link, hrefLang });
|
|
26
|
+
} else {
|
|
27
|
+
hrefLangLinks.push(link);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function populateDirectLinks() {
|
|
32
|
+
languagesWithLocales.forEach((binds) =>
|
|
33
|
+
binds.forEach(({ locale }) => pushLocaleToLinks(locale)),
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function populateRegionIndependentLinks() {
|
|
38
|
+
languagesWithLocales.forEach((binds, regionIndependentLocaleCode) => {
|
|
39
|
+
// When there is no region independent locale of provided locales
|
|
40
|
+
// we still need something as a region independent locale
|
|
41
|
+
const localesArray = Array.from(binds.values()).map(({ locale }) => locale);
|
|
25
42
|
|
|
26
|
-
|
|
27
|
-
|
|
43
|
+
const hasRegionIndependentLocale = localesArray.some(
|
|
44
|
+
(locale) => locale.isRegionIndependent,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
if (hasRegionIndependentLocale) {
|
|
48
|
+
return;
|
|
28
49
|
}
|
|
29
|
-
});
|
|
30
50
|
|
|
31
|
-
|
|
32
|
-
|
|
51
|
+
// Try to find some possible fallback for the regionIndependentLocaleCode from hardcoded list
|
|
52
|
+
// We try to find fallback from provided translations of current regionIndependentLocaleCode
|
|
53
|
+
// If there is no defined fallback in the list we will use just first translation as a region independent translation
|
|
33
54
|
const fallback =
|
|
34
|
-
getFallbackLocale(
|
|
55
|
+
getFallbackLocale(regionIndependentLocaleCode, localesArray) ?? localesArray.at(0);
|
|
35
56
|
|
|
36
57
|
if (fallback) {
|
|
37
|
-
|
|
38
|
-
fallback,
|
|
39
|
-
getTranslationUrl,
|
|
40
|
-
createHref,
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
if (fallbackLink) {
|
|
44
|
-
alternateLanguageFallbackGlobalLinks.push({
|
|
45
|
-
...fallbackLink,
|
|
46
|
-
hrefLang: globalLocaleCode,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
58
|
+
pushLocaleToLinks(fallback, regionIndependentLocaleCode);
|
|
49
59
|
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function populateDefault() {
|
|
64
|
+
// We use english locale as fallback since English is the most common language
|
|
65
|
+
const engFallback = 'en';
|
|
66
|
+
const defaultHrefLang = 'x-default';
|
|
67
|
+
|
|
68
|
+
let isDefaultAddedToLinks = false;
|
|
69
|
+
|
|
70
|
+
// First we try to find region independent english locale (en)
|
|
71
|
+
// If the story has just region independent `en` translation we will use it as default hreflang
|
|
72
|
+
languagesWithLocales.forEach((binds) =>
|
|
73
|
+
binds.forEach(({ locale }) => {
|
|
74
|
+
if (locale.isRegionIndependent && locale.toNeutralLanguageCode() === engFallback) {
|
|
75
|
+
pushLocaleToLinks(locale, defaultHrefLang);
|
|
76
|
+
isDefaultAddedToLinks = true;
|
|
77
|
+
}
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
52
80
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
81
|
+
if (!isDefaultAddedToLinks) {
|
|
82
|
+
// If there is no explicit region independent `en` translation for this story
|
|
83
|
+
// we will try to find some link that already has `en` fallback
|
|
84
|
+
const fallbackFromRegionIndependentLocales = hrefLangLinks.find(
|
|
85
|
+
(alternate) => alternate.hrefLang === engFallback,
|
|
86
|
+
);
|
|
56
87
|
|
|
57
|
-
|
|
88
|
+
if (fallbackFromRegionIndependentLocales) {
|
|
89
|
+
hrefLangLinks.push({
|
|
90
|
+
...fallbackFromRegionIndependentLocales,
|
|
91
|
+
hrefLang: defaultHrefLang,
|
|
92
|
+
});
|
|
93
|
+
isDefaultAddedToLinks = true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
58
96
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
97
|
+
if (!isDefaultAddedToLinks) {
|
|
98
|
+
// If there is no english locale at all we will use is_default language (provided from server)
|
|
99
|
+
languagesWithLocales.forEach((binds) =>
|
|
100
|
+
binds.forEach(({ locale, language }) => {
|
|
101
|
+
if (language.is_default) {
|
|
102
|
+
pushLocaleToLinks(locale, defaultHrefLang);
|
|
103
|
+
isDefaultAddedToLinks = true;
|
|
104
|
+
}
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
66
109
|
|
|
67
|
-
|
|
110
|
+
populateDirectLinks();
|
|
111
|
+
populateRegionIndependentLinks();
|
|
112
|
+
populateDefault();
|
|
68
113
|
|
|
69
|
-
return
|
|
70
|
-
.filter((link): link is Exclude<typeof link, undefined> => Boolean(link))
|
|
71
|
-
.sort((a, b) => a.hrefLang.localeCompare(b.hrefLang));
|
|
114
|
+
return hrefLangLinks.sort((a, b) => a.hrefLang.localeCompare(b.hrefLang));
|
|
72
115
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { NewsroomLanguageSettings } from '@prezly/sdk';
|
|
2
|
+
|
|
3
|
+
import type { LangCode, LocaleCode } from '../../intl';
|
|
4
|
+
import { LocaleObject } from '../../intl';
|
|
5
|
+
|
|
6
|
+
interface LocaleWithLanguage {
|
|
7
|
+
language: NewsroomLanguageSettings;
|
|
8
|
+
locale: LocaleObject;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Group languages by their region independent language code (e.g. "en" for "en-US" and "en-GB").
|
|
13
|
+
*/
|
|
14
|
+
export function bindLanguagesWithLocales(languages: NewsroomLanguageSettings[]) {
|
|
15
|
+
const localesByLangCode = new Map<LangCode, Map<LocaleCode, LocaleWithLanguage>>();
|
|
16
|
+
|
|
17
|
+
languages.forEach((language) => {
|
|
18
|
+
const languageLocale = LocaleObject.fromAnyCode(language.code);
|
|
19
|
+
const regionIndependentLanguageCode = languageLocale.toNeutralLanguageCode();
|
|
20
|
+
let currentLocale = localesByLangCode.get(regionIndependentLanguageCode);
|
|
21
|
+
|
|
22
|
+
if (!currentLocale) {
|
|
23
|
+
currentLocale = new Map();
|
|
24
|
+
localesByLangCode.set(regionIndependentLanguageCode, currentLocale);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
currentLocale.set(languageLocale.toHyphenCode(), { language, locale: languageLocale });
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return localesByLangCode;
|
|
31
|
+
}
|
|
@@ -2,10 +2,9 @@ import type { LocaleObject } from '../../intl';
|
|
|
2
2
|
|
|
3
3
|
export function createAlternateLanguageLink(
|
|
4
4
|
locale: LocaleObject,
|
|
5
|
-
|
|
6
|
-
createHref: (locale: LocaleObject, translationUrl: string) => string,
|
|
5
|
+
generateTranslationUrl: (locale: LocaleObject) => string | undefined,
|
|
7
6
|
) {
|
|
8
|
-
const translationUrl =
|
|
7
|
+
const translationUrl = generateTranslationUrl(locale);
|
|
9
8
|
|
|
10
9
|
if (!translationUrl) {
|
|
11
10
|
return undefined;
|
|
@@ -13,6 +12,6 @@ export function createAlternateLanguageLink(
|
|
|
13
12
|
|
|
14
13
|
return {
|
|
15
14
|
hrefLang: locale.toHyphenCode(),
|
|
16
|
-
href:
|
|
15
|
+
href: translationUrl,
|
|
17
16
|
};
|
|
18
17
|
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { AlternateLanguageLink } from '../../components-nextjs/PageSeo';
|
|
2
|
-
import type { LocaleObject } from '../../intl';
|
|
3
|
-
interface Options {
|
|
4
|
-
alternateLanguageLocales: LocaleObject[];
|
|
5
|
-
alternateLanguageFallbackGlobalLinks: AlternateLanguageLink[];
|
|
6
|
-
defaultLangLocale: LocaleObject | undefined;
|
|
7
|
-
getTranslationUrl: (locale: LocaleObject) => string | undefined;
|
|
8
|
-
createHref: (locale: LocaleObject, translationUrl: string) => string;
|
|
9
|
-
}
|
|
10
|
-
export declare function getDefaultHrefLang({ createHref, defaultLangLocale, getTranslationUrl, alternateLanguageFallbackGlobalLinks, alternateLanguageLocales, }: Options): AlternateLanguageLink | undefined;
|
|
11
|
-
export {};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDefaultHrefLang = void 0;
|
|
4
|
-
const createAlternateLanguageLink_1 = require("./createAlternateLanguageLink");
|
|
5
|
-
function getDefaultHrefLang({ createHref, defaultLangLocale, getTranslationUrl, alternateLanguageFallbackGlobalLinks, alternateLanguageLocales, }) {
|
|
6
|
-
const engFallback = 'en';
|
|
7
|
-
const hrefLang = 'x-default';
|
|
8
|
-
const fallbackFromLocales = alternateLanguageLocales.find((alternate) => alternate.isGlobal && alternate.toNeutralLanguageCode() === engFallback);
|
|
9
|
-
if (fallbackFromLocales) {
|
|
10
|
-
const link = (0, createAlternateLanguageLink_1.createAlternateLanguageLink)(fallbackFromLocales, getTranslationUrl, createHref);
|
|
11
|
-
if (link) {
|
|
12
|
-
return { ...link, hrefLang };
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
const fallbackFromGlobalLocales = alternateLanguageFallbackGlobalLinks.find((alternate) => alternate.hrefLang === engFallback);
|
|
16
|
-
if (fallbackFromGlobalLocales) {
|
|
17
|
-
return { ...fallbackFromGlobalLocales, hrefLang };
|
|
18
|
-
}
|
|
19
|
-
if (defaultLangLocale) {
|
|
20
|
-
const link = (0, createAlternateLanguageLink_1.createAlternateLanguageLink)(defaultLangLocale, getTranslationUrl, createHref);
|
|
21
|
-
if (link) {
|
|
22
|
-
return { ...link, hrefLang };
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
exports.getDefaultHrefLang = getDefaultHrefLang;
|
|
28
|
-
//# sourceMappingURL=getDefaultHrefLang.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getDefaultHrefLang.js","sourceRoot":"","sources":["../../../src/seo/utils/getDefaultHrefLang.ts"],"names":[],"mappings":";;;AAGA,+EAA4E;AAU5E,SAAgB,kBAAkB,CAAC,EAC/B,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,oCAAoC,EACpC,wBAAwB,GAClB;IACN,MAAM,WAAW,GAAG,IAAI,CAAC;IACzB,MAAM,QAAQ,GAAG,WAAW,CAAC;IAE7B,MAAM,mBAAmB,GAAG,wBAAwB,CAAC,IAAI,CACrD,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,qBAAqB,EAAE,KAAK,WAAW,CACzF,CAAC;IAEF,IAAI,mBAAmB,EAAE;QACrB,MAAM,IAAI,GAAG,IAAA,yDAA2B,EACpC,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,CACb,CAAC;QAEF,IAAI,IAAI,EAAE;YACN,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC;SAChC;KACJ;IAED,MAAM,yBAAyB,GAAG,oCAAoC,CAAC,IAAI,CACvE,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,KAAK,WAAW,CACpD,CAAC;IAEF,IAAI,yBAAyB,EAAE;QAC3B,OAAO,EAAE,GAAG,yBAAyB,EAAE,QAAQ,EAAE,CAAC;KACrD;IAED,IAAI,iBAAiB,EAAE;QACnB,MAAM,IAAI,GAAG,IAAA,yDAA2B,EAAC,iBAAiB,EAAE,iBAAiB,EAAE,UAAU,CAAC,CAAC;QAE3F,IAAI,IAAI,EAAE;YACN,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC;SAChC;KACJ;IAED,OAAO,SAAS,CAAC;AACrB,CAAC;AA3CD,gDA2CC"}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { NewsroomLanguageSettings } from '@prezly/sdk';
|
|
2
|
-
import type { LangCode, LocaleCode } from '../../intl';
|
|
3
|
-
import { LocaleObject } from '../../intl';
|
|
4
|
-
export declare function mapLanguagesToLocales(languages: NewsroomLanguageSettings[]): readonly [Map<LangCode, Map<LocaleCode, LocaleObject>>, LocaleObject | undefined];
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.mapLanguagesToLocales = void 0;
|
|
4
|
-
const intl_1 = require("../../intl");
|
|
5
|
-
function mapLanguagesToLocales(languages) {
|
|
6
|
-
let defaultLangLocale;
|
|
7
|
-
const localesByLangCode = new Map();
|
|
8
|
-
languages.forEach((language) => {
|
|
9
|
-
const languageLocale = intl_1.LocaleObject.fromAnyCode(language.code);
|
|
10
|
-
const globalLanguageCode = languageLocale.toNeutralLanguageCode();
|
|
11
|
-
let currentLocale = localesByLangCode.get(globalLanguageCode);
|
|
12
|
-
if (!currentLocale) {
|
|
13
|
-
currentLocale = new Map([[languageLocale.toHyphenCode(), languageLocale]]);
|
|
14
|
-
localesByLangCode.set(globalLanguageCode, currentLocale);
|
|
15
|
-
}
|
|
16
|
-
currentLocale.set(languageLocale.toHyphenCode(), languageLocale);
|
|
17
|
-
if (language.is_default) {
|
|
18
|
-
defaultLangLocale = languageLocale;
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
return [localesByLangCode, defaultLangLocale];
|
|
22
|
-
}
|
|
23
|
-
exports.mapLanguagesToLocales = mapLanguagesToLocales;
|
|
24
|
-
//# sourceMappingURL=mapLanguagesToLocales.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mapLanguagesToLocales.js","sourceRoot":"","sources":["../../../src/seo/utils/mapLanguagesToLocales.ts"],"names":[],"mappings":";;;AAGA,qCAA0C;AAE1C,SAAgB,qBAAqB,CAAC,SAAqC;IACvE,IAAI,iBAA2C,CAAC;IAChD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAA2C,CAAC;IAE7E,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;QAC3B,MAAM,cAAc,GAAG,mBAAY,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC/D,MAAM,kBAAkB,GAAG,cAAc,CAAC,qBAAqB,EAAE,CAAC;QAClE,IAAI,aAAa,GAAG,iBAAiB,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAE9D,IAAI,CAAC,aAAa,EAAE;YAChB,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,YAAY,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;YAC3E,iBAAiB,CAAC,GAAG,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;SAC5D;QAED,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,YAAY,EAAE,EAAE,cAAc,CAAC,CAAC;QAEjE,IAAI,QAAQ,CAAC,UAAU,EAAE;YACrB,iBAAiB,GAAG,cAAc,CAAC;SACtC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,iBAAiB,EAAE,iBAAiB,CAAU,CAAC;AAC3D,CAAC;AAtBD,sDAsBC"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { AlternateLanguageLink } from '../../components-nextjs/PageSeo';
|
|
2
|
-
import type { LocaleObject } from '../../intl';
|
|
3
|
-
|
|
4
|
-
import { createAlternateLanguageLink } from './createAlternateLanguageLink';
|
|
5
|
-
|
|
6
|
-
interface Options {
|
|
7
|
-
alternateLanguageLocales: LocaleObject[];
|
|
8
|
-
alternateLanguageFallbackGlobalLinks: AlternateLanguageLink[];
|
|
9
|
-
defaultLangLocale: LocaleObject | undefined;
|
|
10
|
-
getTranslationUrl: (locale: LocaleObject) => string | undefined;
|
|
11
|
-
createHref: (locale: LocaleObject, translationUrl: string) => string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function getDefaultHrefLang({
|
|
15
|
-
createHref,
|
|
16
|
-
defaultLangLocale,
|
|
17
|
-
getTranslationUrl,
|
|
18
|
-
alternateLanguageFallbackGlobalLinks,
|
|
19
|
-
alternateLanguageLocales,
|
|
20
|
-
}: Options): AlternateLanguageLink | undefined {
|
|
21
|
-
const engFallback = 'en';
|
|
22
|
-
const hrefLang = 'x-default';
|
|
23
|
-
|
|
24
|
-
const fallbackFromLocales = alternateLanguageLocales.find(
|
|
25
|
-
(alternate) => alternate.isGlobal && alternate.toNeutralLanguageCode() === engFallback,
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
if (fallbackFromLocales) {
|
|
29
|
-
const link = createAlternateLanguageLink(
|
|
30
|
-
fallbackFromLocales,
|
|
31
|
-
getTranslationUrl,
|
|
32
|
-
createHref,
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
if (link) {
|
|
36
|
-
return { ...link, hrefLang };
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const fallbackFromGlobalLocales = alternateLanguageFallbackGlobalLinks.find(
|
|
41
|
-
(alternate) => alternate.hrefLang === engFallback,
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
if (fallbackFromGlobalLocales) {
|
|
45
|
-
return { ...fallbackFromGlobalLocales, hrefLang };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (defaultLangLocale) {
|
|
49
|
-
const link = createAlternateLanguageLink(defaultLangLocale, getTranslationUrl, createHref);
|
|
50
|
-
|
|
51
|
-
if (link) {
|
|
52
|
-
return { ...link, hrefLang };
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return undefined;
|
|
57
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { NewsroomLanguageSettings } from '@prezly/sdk';
|
|
2
|
-
|
|
3
|
-
import type { LangCode, LocaleCode } from '../../intl';
|
|
4
|
-
import { LocaleObject } from '../../intl';
|
|
5
|
-
|
|
6
|
-
export function mapLanguagesToLocales(languages: NewsroomLanguageSettings[]) {
|
|
7
|
-
let defaultLangLocale: LocaleObject | undefined;
|
|
8
|
-
const localesByLangCode = new Map<LangCode, Map<LocaleCode, LocaleObject>>();
|
|
9
|
-
|
|
10
|
-
languages.forEach((language) => {
|
|
11
|
-
const languageLocale = LocaleObject.fromAnyCode(language.code);
|
|
12
|
-
const globalLanguageCode = languageLocale.toNeutralLanguageCode();
|
|
13
|
-
let currentLocale = localesByLangCode.get(globalLanguageCode);
|
|
14
|
-
|
|
15
|
-
if (!currentLocale) {
|
|
16
|
-
currentLocale = new Map([[languageLocale.toHyphenCode(), languageLocale]]);
|
|
17
|
-
localesByLangCode.set(globalLanguageCode, currentLocale);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
currentLocale.set(languageLocale.toHyphenCode(), languageLocale);
|
|
21
|
-
|
|
22
|
-
if (language.is_default) {
|
|
23
|
-
defaultLangLocale = languageLocale;
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
return [localesByLangCode, defaultLangLocale] as const;
|
|
28
|
-
}
|