@prezly/theme-kit-nextjs 1.0.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/LICENSE +21 -0
- package/README.md +28 -0
- package/build/adapter-nextjs/getBasePageProps.d.ts +9 -0
- package/build/adapter-nextjs/getBasePageProps.js +11 -0
- package/build/adapter-nextjs/getBasePageProps.js.map +1 -0
- package/build/adapter-nextjs/index.d.ts +2 -0
- package/build/adapter-nextjs/index.js +3 -0
- package/build/adapter-nextjs/index.js.map +1 -0
- package/build/adapter-nextjs/processRequest.d.ts +3 -0
- package/build/adapter-nextjs/processRequest.js +20 -0
- package/build/adapter-nextjs/processRequest.js.map +1 -0
- package/build/data-fetching/api/PrezlyApi.d.ts +43 -0
- package/build/data-fetching/api/PrezlyApi.js +139 -0
- package/build/data-fetching/api/PrezlyApi.js.map +1 -0
- package/build/data-fetching/api/getPrezlyApi.d.ts +4 -0
- package/build/data-fetching/api/getPrezlyApi.js +17 -0
- package/build/data-fetching/api/getPrezlyApi.js.map +1 -0
- package/build/data-fetching/api/index.d.ts +2 -0
- package/build/data-fetching/api/index.js +3 -0
- package/build/data-fetching/api/index.js.map +1 -0
- package/build/data-fetching/api/languages.d.ts +18 -0
- package/build/data-fetching/api/languages.js +117 -0
- package/build/data-fetching/api/languages.js.map +1 -0
- package/build/data-fetching/api/queries.d.ts +45 -0
- package/build/data-fetching/api/queries.js +35 -0
- package/build/data-fetching/api/queries.js.map +1 -0
- package/build/data-fetching/constants.d.ts +2 -0
- package/build/data-fetching/constants.js +3 -0
- package/build/data-fetching/constants.js.map +1 -0
- package/build/data-fetching/getAssetsUrl.d.ts +1 -0
- package/build/data-fetching/getAssetsUrl.js +5 -0
- package/build/data-fetching/getAssetsUrl.js.map +1 -0
- package/build/data-fetching/getLocalizedCategoryData.d.ts +10 -0
- package/build/data-fetching/getLocalizedCategoryData.js +31 -0
- package/build/data-fetching/getLocalizedCategoryData.js.map +1 -0
- package/build/data-fetching/getNewsroomLogoUrl.d.ts +3 -0
- package/build/data-fetching/getNewsroomLogoUrl.js +14 -0
- package/build/data-fetching/getNewsroomLogoUrl.js.map +1 -0
- package/build/data-fetching/getPrivacyPortalUrl.d.ts +8 -0
- package/build/data-fetching/getPrivacyPortalUrl.js +9 -0
- package/build/data-fetching/getPrivacyPortalUrl.js.map +1 -0
- package/build/data-fetching/getStoryPublicationDate.d.ts +3 -0
- package/build/data-fetching/getStoryPublicationDate.jsx +10 -0
- package/build/data-fetching/getStoryPublicationDate.jsx.map +1 -0
- package/build/data-fetching/getUploadcareGroupUrl.d.ts +1 -0
- package/build/data-fetching/getUploadcareGroupUrl.js +5 -0
- package/build/data-fetching/getUploadcareGroupUrl.js.map +1 -0
- package/build/data-fetching/index.d.ts +9 -0
- package/build/data-fetching/index.js +10 -0
- package/build/data-fetching/index.js.map +1 -0
- package/build/data-fetching/lib/getAlgoliaSettings.d.ts +4 -0
- package/build/data-fetching/lib/getAlgoliaSettings.js +18 -0
- package/build/data-fetching/lib/getAlgoliaSettings.js.map +1 -0
- package/build/data-fetching/lib/getEnvVariables.d.ts +4 -0
- package/build/data-fetching/lib/getEnvVariables.js +37 -0
- package/build/data-fetching/lib/getEnvVariables.js.map +1 -0
- package/build/data-fetching/types.d.ts +11 -0
- package/build/data-fetching/types.js +2 -0
- package/build/data-fetching/types.js.map +1 -0
- package/build/index.d.ts +5 -0
- package/build/index.js +6 -0
- package/build/index.js.map +1 -0
- package/build/intl/index.d.ts +4 -0
- package/build/intl/index.js +5 -0
- package/build/intl/index.js.map +1 -0
- package/build/intl/lang.d.ts +12 -0
- package/build/intl/lang.js +25 -0
- package/build/intl/lang.js.map +1 -0
- package/build/intl/locale.d.ts +10 -0
- package/build/intl/locale.js +93 -0
- package/build/intl/locale.js.map +1 -0
- package/build/intl/localeConfig.d.ts +2 -0
- package/build/intl/localeConfig.js +113 -0
- package/build/intl/localeConfig.js.map +1 -0
- package/build/intl/localeObject.d.ts +22 -0
- package/build/intl/localeObject.js +59 -0
- package/build/intl/localeObject.js.map +1 -0
- package/build/newsroom-context/context.d.ts +26 -0
- package/build/newsroom-context/context.jsx +22 -0
- package/build/newsroom-context/context.jsx.map +1 -0
- package/build/newsroom-context/hooks/index.d.ts +11 -0
- package/build/newsroom-context/hooks/index.js +12 -0
- package/build/newsroom-context/hooks/index.js.map +1 -0
- package/build/newsroom-context/hooks/useAlgoliaSettings.d.ts +1 -0
- package/build/newsroom-context/hooks/useAlgoliaSettings.js +6 -0
- package/build/newsroom-context/hooks/useAlgoliaSettings.js.map +1 -0
- package/build/newsroom-context/hooks/useCategories.d.ts +1 -0
- package/build/newsroom-context/hooks/useCategories.js +6 -0
- package/build/newsroom-context/hooks/useCategories.js.map +1 -0
- package/build/newsroom-context/hooks/useCompanyInformation.d.ts +1 -0
- package/build/newsroom-context/hooks/useCompanyInformation.js +6 -0
- package/build/newsroom-context/hooks/useCompanyInformation.js.map +1 -0
- package/build/newsroom-context/hooks/useCurrentLocale.d.ts +1 -0
- package/build/newsroom-context/hooks/useCurrentLocale.js +6 -0
- package/build/newsroom-context/hooks/useCurrentLocale.js.map +1 -0
- package/build/newsroom-context/hooks/useGetLinkLocaleSlug.d.ts +2 -0
- package/build/newsroom-context/hooks/useGetLinkLocaleSlug.js +21 -0
- package/build/newsroom-context/hooks/useGetLinkLocaleSlug.js.map +1 -0
- package/build/newsroom-context/hooks/useGetTranslationUrl.d.ts +2 -0
- package/build/newsroom-context/hooks/useGetTranslationUrl.js +36 -0
- package/build/newsroom-context/hooks/useGetTranslationUrl.js.map +1 -0
- package/build/newsroom-context/hooks/useLanguages.d.ts +1 -0
- package/build/newsroom-context/hooks/useLanguages.js +6 -0
- package/build/newsroom-context/hooks/useLanguages.js.map +1 -0
- package/build/newsroom-context/hooks/useNewsroom.d.ts +1 -0
- package/build/newsroom-context/hooks/useNewsroom.js +6 -0
- package/build/newsroom-context/hooks/useNewsroom.js.map +1 -0
- package/build/newsroom-context/hooks/useNewsroomContext.d.ts +2 -0
- package/build/newsroom-context/hooks/useNewsroomContext.js +12 -0
- package/build/newsroom-context/hooks/useNewsroomContext.js.map +1 -0
- package/build/newsroom-context/hooks/useSelectedCategory.d.ts +1 -0
- package/build/newsroom-context/hooks/useSelectedCategory.js +6 -0
- package/build/newsroom-context/hooks/useSelectedCategory.js.map +1 -0
- package/build/newsroom-context/hooks/useSelectedStory.d.ts +1 -0
- package/build/newsroom-context/hooks/useSelectedStory.js +6 -0
- package/build/newsroom-context/hooks/useSelectedStory.js.map +1 -0
- package/build/newsroom-context/index.d.ts +2 -0
- package/build/newsroom-context/index.js +3 -0
- package/build/newsroom-context/index.js.map +1 -0
- package/build/types.d.ts +38 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/package.json +60 -0
- package/src/@types/global.d.ts +7 -0
- package/src/adapter-nextjs/getBasePageProps.ts +23 -0
- package/src/adapter-nextjs/index.ts +2 -0
- package/src/adapter-nextjs/processRequest.ts +31 -0
- package/src/data-fetching/api/PrezlyApi.ts +240 -0
- package/src/data-fetching/api/getPrezlyApi.ts +24 -0
- package/src/data-fetching/api/index.ts +2 -0
- package/src/data-fetching/api/languages.ts +172 -0
- package/src/data-fetching/api/queries.ts +44 -0
- package/src/data-fetching/constants.ts +2 -0
- package/src/data-fetching/getAssetsUrl.ts +5 -0
- package/src/data-fetching/getLocalizedCategoryData.ts +47 -0
- package/src/data-fetching/getNewsroomLogoUrl.ts +21 -0
- package/src/data-fetching/getPrivacyPortalUrl.ts +22 -0
- package/src/data-fetching/getStoryPublicationDate.tsx +15 -0
- package/src/data-fetching/getUploadcareGroupUrl.ts +5 -0
- package/src/data-fetching/index.ts +9 -0
- package/src/data-fetching/lib/getAlgoliaSettings.ts +29 -0
- package/src/data-fetching/lib/getEnvVariables.ts +44 -0
- package/src/data-fetching/types.ts +12 -0
- package/src/index.ts +5 -0
- package/src/intl/index.ts +4 -0
- package/src/intl/lang.ts +36 -0
- package/src/intl/locale.ts +118 -0
- package/src/intl/localeConfig.js +116 -0
- package/src/intl/localeObject.ts +73 -0
- package/src/newsroom-context/context.tsx +73 -0
- package/src/newsroom-context/hooks/index.ts +11 -0
- package/src/newsroom-context/hooks/useAlgoliaSettings.ts +7 -0
- package/src/newsroom-context/hooks/useCategories.ts +7 -0
- package/src/newsroom-context/hooks/useCompanyInformation.ts +7 -0
- package/src/newsroom-context/hooks/useCurrentLocale.ts +7 -0
- package/src/newsroom-context/hooks/useGetLinkLocaleSlug.ts +33 -0
- package/src/newsroom-context/hooks/useGetTranslationUrl.ts +61 -0
- package/src/newsroom-context/hooks/useLanguages.ts +7 -0
- package/src/newsroom-context/hooks/useNewsroom.ts +7 -0
- package/src/newsroom-context/hooks/useNewsroomContext.ts +14 -0
- package/src/newsroom-context/hooks/useSelectedCategory.ts +7 -0
- package/src/newsroom-context/hooks/useSelectedStory.ts +7 -0
- package/src/newsroom-context/index.ts +2 -0
- package/src/types.ts +56 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { IncomingMessage } from 'http';
|
|
2
|
+
import parseDataUrl from 'parse-data-url';
|
|
3
|
+
|
|
4
|
+
import type { PrezlyEnv } from '../types';
|
|
5
|
+
|
|
6
|
+
const decodeJson = (json: string): Record<string, any> => {
|
|
7
|
+
try {
|
|
8
|
+
const decoded = JSON.parse(json);
|
|
9
|
+
if (decoded && typeof decoded === 'object') {
|
|
10
|
+
return decoded;
|
|
11
|
+
}
|
|
12
|
+
} catch {
|
|
13
|
+
// passthru
|
|
14
|
+
}
|
|
15
|
+
return {};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const decodeHttpEnv = (header: string): Record<string, any> => {
|
|
19
|
+
if (header.startsWith('data:')) {
|
|
20
|
+
const parsed = parseDataUrl(header);
|
|
21
|
+
if (parsed && parsed.contentType === 'application/json') {
|
|
22
|
+
const data = parsed.toBuffer().toString('utf-8');
|
|
23
|
+
return decodeJson(data);
|
|
24
|
+
}
|
|
25
|
+
return {}; // unsupported data-uri
|
|
26
|
+
}
|
|
27
|
+
return decodeJson(header);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const getEnvVariables = (req?: IncomingMessage): PrezlyEnv => {
|
|
31
|
+
if (process.browser) {
|
|
32
|
+
throw new Error('"getEnvVariables" should only be used on back-end side.');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const headerName = (process.env.HTTP_ENV_HEADER || '').toLowerCase();
|
|
36
|
+
|
|
37
|
+
if (headerName && req) {
|
|
38
|
+
const header = req.headers[headerName] as string | undefined;
|
|
39
|
+
const httpEnv = decodeHttpEnv(header || '');
|
|
40
|
+
return { ...process.env, ...httpEnv };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return { ...process.env };
|
|
44
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface AlgoliaSettings {
|
|
2
|
+
ALGOLIA_API_KEY: string;
|
|
3
|
+
ALGOLIA_APP_ID: string;
|
|
4
|
+
ALGOLIA_INDEX: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface PrezlyNewsroomEnv {
|
|
8
|
+
PREZLY_ACCESS_TOKEN: string;
|
|
9
|
+
PREZLY_NEWSROOM_UUID: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface PrezlyEnv extends PrezlyNewsroomEnv, AlgoliaSettings {}
|
package/src/index.ts
ADDED
package/src/intl/lang.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { CultureRef, NewsroomLanguageSettings } from '@prezly/sdk';
|
|
2
|
+
|
|
3
|
+
function isOnlyCulture(culture: CultureRef, languages: NewsroomLanguageSettings[]): boolean {
|
|
4
|
+
const numberOfLanguages = languages.filter(
|
|
5
|
+
({ locale: { language_code } }) => language_code === culture.language_code,
|
|
6
|
+
).length;
|
|
7
|
+
|
|
8
|
+
return numberOfLanguages === 1;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* If there's only one culture used in a specific language,
|
|
13
|
+
* we strip the culture name completely.
|
|
14
|
+
*
|
|
15
|
+
* Examples:
|
|
16
|
+
* - English (Global), Spanish (Spain)
|
|
17
|
+
* -> English, Spanish
|
|
18
|
+
* - English (Global), English (UK), Spanish (Spain)
|
|
19
|
+
* -> English (Global), English (UK), Spanish
|
|
20
|
+
*/
|
|
21
|
+
export function getLanguageDisplayName(
|
|
22
|
+
language: NewsroomLanguageSettings,
|
|
23
|
+
languages: NewsroomLanguageSettings[],
|
|
24
|
+
): string {
|
|
25
|
+
const { locale } = language;
|
|
26
|
+
|
|
27
|
+
if (isOnlyCulture(locale, languages)) {
|
|
28
|
+
const cultureNameIndex = locale.native_name.indexOf('(');
|
|
29
|
+
|
|
30
|
+
if (cultureNameIndex !== -1) {
|
|
31
|
+
return locale.native_name.slice(0, cultureNameIndex - 1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return locale.native_name;
|
|
36
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { Redirect } from 'next';
|
|
2
|
+
import { ParsedUrlQuery, stringify } from 'querystring';
|
|
3
|
+
|
|
4
|
+
import { BasePageProps } from '../types';
|
|
5
|
+
|
|
6
|
+
import { LocaleObject } from './localeObject';
|
|
7
|
+
|
|
8
|
+
export const DEFAULT_LOCALE = 'en';
|
|
9
|
+
export const DUMMY_DEFAULT_LOCALE = 'qps-ploc';
|
|
10
|
+
|
|
11
|
+
const SUPPORTED_LOCALES = [
|
|
12
|
+
'af',
|
|
13
|
+
'ar',
|
|
14
|
+
'az',
|
|
15
|
+
'be',
|
|
16
|
+
'bg',
|
|
17
|
+
'cs',
|
|
18
|
+
'da',
|
|
19
|
+
'de',
|
|
20
|
+
'el',
|
|
21
|
+
'en',
|
|
22
|
+
'es',
|
|
23
|
+
'et',
|
|
24
|
+
'fi',
|
|
25
|
+
'fil',
|
|
26
|
+
'fr',
|
|
27
|
+
'ga',
|
|
28
|
+
'he',
|
|
29
|
+
'hi',
|
|
30
|
+
'hr',
|
|
31
|
+
'hu',
|
|
32
|
+
'id',
|
|
33
|
+
'it',
|
|
34
|
+
'ja',
|
|
35
|
+
'kk',
|
|
36
|
+
'ko',
|
|
37
|
+
'lt',
|
|
38
|
+
'lv',
|
|
39
|
+
'mt',
|
|
40
|
+
'nl',
|
|
41
|
+
'no',
|
|
42
|
+
'pl',
|
|
43
|
+
'pt-BR',
|
|
44
|
+
'pt',
|
|
45
|
+
'ro',
|
|
46
|
+
'ru',
|
|
47
|
+
'sk',
|
|
48
|
+
'sl',
|
|
49
|
+
'sv',
|
|
50
|
+
'th',
|
|
51
|
+
'tr',
|
|
52
|
+
'uk',
|
|
53
|
+
'ur',
|
|
54
|
+
'uz',
|
|
55
|
+
'vi',
|
|
56
|
+
'zh-CN',
|
|
57
|
+
'zh-TW',
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
export function getSupportedLocaleIsoCode(locale: LocaleObject): string {
|
|
61
|
+
const localeIsoCode = locale.toHyphenCode();
|
|
62
|
+
|
|
63
|
+
const isSupportedLocale =
|
|
64
|
+
localeIsoCode.length >= 2 && SUPPORTED_LOCALES.includes(localeIsoCode);
|
|
65
|
+
if (isSupportedLocale) {
|
|
66
|
+
return localeIsoCode;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const language = localeIsoCode.slice(0, 2);
|
|
70
|
+
const isSupportedLanguage = SUPPORTED_LOCALES.includes(language);
|
|
71
|
+
if (isSupportedLanguage) {
|
|
72
|
+
return language;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return DEFAULT_LOCALE;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function getRedirectToCanonicalLocale(
|
|
79
|
+
basePageProps: BasePageProps,
|
|
80
|
+
nextLocaleIsoCode: string | undefined,
|
|
81
|
+
redirectPath: string,
|
|
82
|
+
query?: ParsedUrlQuery,
|
|
83
|
+
): Redirect | undefined {
|
|
84
|
+
const { shortestLocaleCode } = basePageProps;
|
|
85
|
+
const shortestLocaleSlug = shortestLocaleCode
|
|
86
|
+
? LocaleObject.fromAnyCode(shortestLocaleCode).toUrlSlug()
|
|
87
|
+
: shortestLocaleCode;
|
|
88
|
+
|
|
89
|
+
if (nextLocaleIsoCode === DUMMY_DEFAULT_LOCALE) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (shortestLocaleSlug !== nextLocaleIsoCode) {
|
|
94
|
+
const prefixedPath =
|
|
95
|
+
redirectPath && !redirectPath.startsWith('/') ? `/${redirectPath}` : redirectPath;
|
|
96
|
+
|
|
97
|
+
const urlQuery = query ? `?${stringify(query)}` : '';
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
destination: shortestLocaleSlug
|
|
101
|
+
? `/${shortestLocaleSlug}${prefixedPath}${urlQuery}`
|
|
102
|
+
: `${prefixedPath}${urlQuery}`,
|
|
103
|
+
permanent: false,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function getLocaleDirection(locale: LocaleObject): 'ltr' | 'rtl' {
|
|
111
|
+
const neutralLanguageCode = locale.toNeutralLanguageCode();
|
|
112
|
+
|
|
113
|
+
if (['ar', 'he', 'ur'].includes(neutralLanguageCode)) {
|
|
114
|
+
return 'rtl';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return 'ltr';
|
|
118
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// This list is pulled from the main Prezly application. The underscores are replaced with dashes.
|
|
2
|
+
const supportedLocales = [
|
|
3
|
+
'af-ZA',
|
|
4
|
+
'ar',
|
|
5
|
+
'ar-AE',
|
|
6
|
+
'ar-BH',
|
|
7
|
+
'ar-QA',
|
|
8
|
+
'ar-SA',
|
|
9
|
+
'az',
|
|
10
|
+
'be',
|
|
11
|
+
'bg-BG',
|
|
12
|
+
'cs-CZ',
|
|
13
|
+
'da-DK',
|
|
14
|
+
'de',
|
|
15
|
+
'de-DE',
|
|
16
|
+
'de-AT',
|
|
17
|
+
'de-CH',
|
|
18
|
+
'el-GR',
|
|
19
|
+
'en',
|
|
20
|
+
'en-US',
|
|
21
|
+
'en-AE',
|
|
22
|
+
'en-AU',
|
|
23
|
+
'en-BD',
|
|
24
|
+
'en-BE',
|
|
25
|
+
'en-BH',
|
|
26
|
+
'en-CA',
|
|
27
|
+
'en-CN',
|
|
28
|
+
'en-DE',
|
|
29
|
+
'en-DK',
|
|
30
|
+
'en-GB',
|
|
31
|
+
'en-HK',
|
|
32
|
+
'en-ID',
|
|
33
|
+
'en-IE',
|
|
34
|
+
'en-IL',
|
|
35
|
+
'en-IN',
|
|
36
|
+
'en-JP',
|
|
37
|
+
'en-KH',
|
|
38
|
+
'en-KR',
|
|
39
|
+
'en-LK',
|
|
40
|
+
'en-MV',
|
|
41
|
+
'en-MM',
|
|
42
|
+
'en-MY',
|
|
43
|
+
'en-NP',
|
|
44
|
+
'en-NZ',
|
|
45
|
+
'en-PH',
|
|
46
|
+
'en-PK',
|
|
47
|
+
'en-QA',
|
|
48
|
+
'en-SA',
|
|
49
|
+
'en-SG',
|
|
50
|
+
'en-TH',
|
|
51
|
+
'en-TW',
|
|
52
|
+
'en-VN',
|
|
53
|
+
'en-ZA',
|
|
54
|
+
'es',
|
|
55
|
+
'es-ES',
|
|
56
|
+
'es-MX',
|
|
57
|
+
'et-EE',
|
|
58
|
+
'fi-FI',
|
|
59
|
+
'fil',
|
|
60
|
+
'fr',
|
|
61
|
+
'fr-BE',
|
|
62
|
+
'fr-FR',
|
|
63
|
+
'fr-CA',
|
|
64
|
+
'fr-LU',
|
|
65
|
+
'ga-IE',
|
|
66
|
+
'he-IL',
|
|
67
|
+
'hi-IN',
|
|
68
|
+
'hr-HR',
|
|
69
|
+
'hu-HU',
|
|
70
|
+
'id-ID',
|
|
71
|
+
'it-IT',
|
|
72
|
+
'ja-JP',
|
|
73
|
+
'kk',
|
|
74
|
+
'ko-KR',
|
|
75
|
+
'ky',
|
|
76
|
+
'lt-LT',
|
|
77
|
+
'lv-LV',
|
|
78
|
+
'mt-MT',
|
|
79
|
+
'ms-MY',
|
|
80
|
+
'nb-NO',
|
|
81
|
+
'nl',
|
|
82
|
+
'nl-BE',
|
|
83
|
+
'nl-NL',
|
|
84
|
+
'pl-PL',
|
|
85
|
+
'pt',
|
|
86
|
+
'pt-BR',
|
|
87
|
+
'pt-PT',
|
|
88
|
+
'ro-RO',
|
|
89
|
+
'ru-RU',
|
|
90
|
+
'sk-SK',
|
|
91
|
+
'sl-SI',
|
|
92
|
+
'sv-SE',
|
|
93
|
+
'th-TH',
|
|
94
|
+
'tr-TR',
|
|
95
|
+
'uk-UA',
|
|
96
|
+
'ur-PK',
|
|
97
|
+
'uz',
|
|
98
|
+
'vi-VN',
|
|
99
|
+
'zh-Hant',
|
|
100
|
+
'zh-HK',
|
|
101
|
+
'zh-TW',
|
|
102
|
+
'zh-CN',
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
const lowercaseLocales = supportedLocales.map((l) => l.toLowerCase());
|
|
106
|
+
|
|
107
|
+
// Get all permutations for the shorter locale codes supported by Prezly (e.g. short region codes)
|
|
108
|
+
const lowercaseLocalPermutations = Array.from(
|
|
109
|
+
new Set([
|
|
110
|
+
...lowercaseLocales,
|
|
111
|
+
...lowercaseLocales.map((code) => code.split('-')[0]),
|
|
112
|
+
...lowercaseLocales.map((code) => code.split('-')[1]).filter(Boolean),
|
|
113
|
+
]),
|
|
114
|
+
).sort();
|
|
115
|
+
|
|
116
|
+
module.exports = lowercaseLocalPermutations;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import localeConfig from './localeConfig';
|
|
2
|
+
|
|
3
|
+
export class LocaleObject {
|
|
4
|
+
/**
|
|
5
|
+
* Hyphen-separated locale code.
|
|
6
|
+
* Examples: `nl-BE`, `en-US`, `fr`, `fil`
|
|
7
|
+
*/
|
|
8
|
+
private localeCode: string;
|
|
9
|
+
|
|
10
|
+
private constructor(localeCode: string) {
|
|
11
|
+
if (localeCode.indexOf('_') !== -1) {
|
|
12
|
+
throw new Error('Invalid locale code provided!');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const [language, region] = localeCode.split('-');
|
|
16
|
+
|
|
17
|
+
if (region) {
|
|
18
|
+
this.localeCode = [language, region.toUpperCase()].join('-');
|
|
19
|
+
} else {
|
|
20
|
+
this.localeCode = language;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param localeCode Locale code in any of the formats below.
|
|
26
|
+
* Examples:
|
|
27
|
+
* - Hyphen-codes: `nl-BE`, `en-US`, `fr`, `fil`
|
|
28
|
+
* - Underscore-codes: `nl_BE`, `en_US`, `fr`, `fil`
|
|
29
|
+
* - Slugs: `nl-be`, `en-us`, `fr`, `fil`
|
|
30
|
+
*/
|
|
31
|
+
public static fromAnyCode(localeCode: string): LocaleObject {
|
|
32
|
+
const lowercaseCode = localeCode.toLowerCase().replace('_', '-');
|
|
33
|
+
const foundCode = localeConfig.find((code) => code === lowercaseCode);
|
|
34
|
+
|
|
35
|
+
if (!foundCode) {
|
|
36
|
+
throw new Error(`Unsupported locale code provided: "${lowercaseCode}"`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return new LocaleObject(foundCode);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public toHyphenCode(): string {
|
|
43
|
+
return this.localeCode;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public toUnderscoreCode(): string {
|
|
47
|
+
return this.localeCode.replace('-', '_');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public toUrlSlug(): string {
|
|
51
|
+
return this.localeCode.toLowerCase();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public toNeutralLanguageCode(): string {
|
|
55
|
+
const [language] = this.localeCode.split('-');
|
|
56
|
+
|
|
57
|
+
return language;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public toRegionCode(): string {
|
|
61
|
+
const [language, region] = this.localeCode.split('-');
|
|
62
|
+
|
|
63
|
+
if (!region) {
|
|
64
|
+
return language.toUpperCase();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return region.toUpperCase();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public isEqual(anotherLocale: LocaleObject) {
|
|
71
|
+
return anotherLocale.toHyphenCode() === this.localeCode;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Category,
|
|
3
|
+
Newsroom,
|
|
4
|
+
NewsroomCompanyInformation,
|
|
5
|
+
NewsroomContact,
|
|
6
|
+
NewsroomLanguageSettings,
|
|
7
|
+
NewsroomThemePreset,
|
|
8
|
+
Story,
|
|
9
|
+
} from '@prezly/sdk';
|
|
10
|
+
import { createContext, FunctionComponent, useMemo } from 'react';
|
|
11
|
+
|
|
12
|
+
import type { AlgoliaSettings } from '../data-fetching';
|
|
13
|
+
import { LocaleObject } from '../intl';
|
|
14
|
+
import { Translations } from '../types';
|
|
15
|
+
|
|
16
|
+
export interface INewsroomContext {
|
|
17
|
+
newsroom: Newsroom;
|
|
18
|
+
companyInformation: NewsroomCompanyInformation;
|
|
19
|
+
categories: Category[];
|
|
20
|
+
contacts?: NewsroomContact[];
|
|
21
|
+
selectedCategory?: Category;
|
|
22
|
+
selectedStory?: Story;
|
|
23
|
+
languages: NewsroomLanguageSettings[];
|
|
24
|
+
locale: LocaleObject;
|
|
25
|
+
hasError?: boolean;
|
|
26
|
+
themePreset: NewsroomThemePreset;
|
|
27
|
+
algoliaSettings: AlgoliaSettings;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface Props extends Omit<INewsroomContext, 'locale'> {
|
|
31
|
+
isTrackingEnabled?: boolean;
|
|
32
|
+
localeCode: string;
|
|
33
|
+
translations?: Translations;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const NewsroomContext = createContext<INewsroomContext | undefined>(undefined);
|
|
37
|
+
|
|
38
|
+
export const NewsroomContextProvider: FunctionComponent<Props> = ({
|
|
39
|
+
categories,
|
|
40
|
+
contacts,
|
|
41
|
+
newsroom,
|
|
42
|
+
selectedCategory,
|
|
43
|
+
selectedStory,
|
|
44
|
+
companyInformation,
|
|
45
|
+
languages,
|
|
46
|
+
localeCode,
|
|
47
|
+
hasError,
|
|
48
|
+
themePreset,
|
|
49
|
+
algoliaSettings,
|
|
50
|
+
children,
|
|
51
|
+
}) => {
|
|
52
|
+
const locale = useMemo(() => LocaleObject.fromAnyCode(localeCode || 'en'), [localeCode]);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<NewsroomContext.Provider
|
|
56
|
+
value={{
|
|
57
|
+
categories,
|
|
58
|
+
contacts,
|
|
59
|
+
newsroom,
|
|
60
|
+
selectedCategory,
|
|
61
|
+
selectedStory,
|
|
62
|
+
companyInformation,
|
|
63
|
+
languages,
|
|
64
|
+
locale,
|
|
65
|
+
hasError,
|
|
66
|
+
themePreset,
|
|
67
|
+
algoliaSettings,
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
{children}
|
|
71
|
+
</NewsroomContext.Provider>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './useAlgoliaSettings';
|
|
2
|
+
export * from './useCategories';
|
|
3
|
+
export * from './useCompanyInformation';
|
|
4
|
+
export * from './useCurrentLocale';
|
|
5
|
+
export * from './useGetLinkLocaleSlug';
|
|
6
|
+
export * from './useGetTranslationUrl';
|
|
7
|
+
export * from './useLanguages';
|
|
8
|
+
export * from './useNewsroom';
|
|
9
|
+
export * from './useNewsroomContext';
|
|
10
|
+
export * from './useSelectedCategory';
|
|
11
|
+
export * from './useSelectedStory';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { NewsroomLanguageSettings } from '@prezly/sdk';
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
|
|
4
|
+
import { getShortestLocaleCode } from '../../data-fetching';
|
|
5
|
+
import { LocaleObject } from '../../intl';
|
|
6
|
+
|
|
7
|
+
import { useCurrentLocale } from './useCurrentLocale';
|
|
8
|
+
import { useLanguages } from './useLanguages';
|
|
9
|
+
|
|
10
|
+
// Determine correct locale slug for the link (trying to shorten the locale code if possible)
|
|
11
|
+
function getLinkLocaleSlug(
|
|
12
|
+
languages: NewsroomLanguageSettings[],
|
|
13
|
+
locale: LocaleObject,
|
|
14
|
+
): string | false {
|
|
15
|
+
const shortestLocaleCode = getShortestLocaleCode(languages, locale);
|
|
16
|
+
// When navigating to default language, we don't append the locale to the URL.
|
|
17
|
+
if (!shortestLocaleCode) {
|
|
18
|
+
return shortestLocaleCode;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return LocaleObject.fromAnyCode(shortestLocaleCode).toUrlSlug();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function useGetLinkLocaleSlug() {
|
|
25
|
+
const currentLocale = useCurrentLocale();
|
|
26
|
+
const languages = useLanguages();
|
|
27
|
+
|
|
28
|
+
// The `locale` parameter is mainly used for Language Dropdown
|
|
29
|
+
return useCallback(
|
|
30
|
+
(locale?: LocaleObject) => getLinkLocaleSlug(languages, locale || currentLocale),
|
|
31
|
+
[languages, currentLocale],
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Category, Story } from '@prezly/sdk';
|
|
2
|
+
import { useRouter } from 'next/router';
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
|
|
5
|
+
import { getCategoryHasTranslation, getCategoryUrl } from '../../data-fetching';
|
|
6
|
+
import { LocaleObject } from '../../intl';
|
|
7
|
+
|
|
8
|
+
import { useSelectedCategory } from './useSelectedCategory';
|
|
9
|
+
import { useSelectedStory } from './useSelectedStory';
|
|
10
|
+
|
|
11
|
+
// Determine correct URL for translated stories/categories with a fallback to homepage
|
|
12
|
+
function getTranslationUrl(
|
|
13
|
+
locale: LocaleObject,
|
|
14
|
+
path: string,
|
|
15
|
+
selectedCategory?: Category,
|
|
16
|
+
selectedStory?: Story,
|
|
17
|
+
noFallback?: boolean,
|
|
18
|
+
) {
|
|
19
|
+
if (selectedCategory) {
|
|
20
|
+
if (getCategoryHasTranslation(selectedCategory, locale)) {
|
|
21
|
+
return getCategoryUrl(selectedCategory, locale);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (noFallback) {
|
|
25
|
+
return '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return '/';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const localeCode = locale.toUnderscoreCode();
|
|
32
|
+
|
|
33
|
+
if (selectedStory && selectedStory.culture.locale !== localeCode) {
|
|
34
|
+
const translatedStory = selectedStory.translations.find(
|
|
35
|
+
({ culture }) => culture.locale === localeCode,
|
|
36
|
+
);
|
|
37
|
+
if (translatedStory) {
|
|
38
|
+
return `/${translatedStory.slug}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (noFallback) {
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return '/';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return path;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function useGetTranslationUrl() {
|
|
52
|
+
const { asPath } = useRouter();
|
|
53
|
+
const selectedCategory = useSelectedCategory();
|
|
54
|
+
const selectedStory = useSelectedStory();
|
|
55
|
+
|
|
56
|
+
return useCallback(
|
|
57
|
+
(locale: LocaleObject, noFallback?: boolean) =>
|
|
58
|
+
getTranslationUrl(locale, asPath, selectedCategory, selectedStory, noFallback),
|
|
59
|
+
[asPath, selectedCategory, selectedStory],
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
import { INewsroomContext, NewsroomContext } from '../context';
|
|
4
|
+
|
|
5
|
+
export const useNewsroomContext = () => {
|
|
6
|
+
// TS Compiler is having a hard time figuring this type implicitly, so we have to set it explicitly
|
|
7
|
+
// See https://github.com/microsoft/TypeScript/issues/5711#issuecomment-340283439
|
|
8
|
+
const newsroomContext: INewsroomContext | undefined = useContext(NewsroomContext);
|
|
9
|
+
if (!newsroomContext) {
|
|
10
|
+
throw new Error('No `NewsroomContextProvider` found when calling `useNewsroomContext`');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return newsroomContext;
|
|
14
|
+
};
|