Skip to content
This repository was archived by the owner on Dec 27, 2022. It is now read-only.

Commit c72d6c7

Browse files
authored
Merge pull request #310 from strapi/plugin-options-i18n
Fix i18n support
2 parents 322b842 + da12da5 commit c72d6c7

File tree

4 files changed

+140
-19
lines changed

4 files changed

+140
-19
lines changed

README.md

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ Source plugin for pulling documents into Gatsby from a Strapi API.
88
<summary><strong>Table of contents</strong></summary>
99

1010
- [gatsby-source-strapi](#gatsby-source-strapi)
11-
- [Install](#installing-the-plugin)
11+
- [Installing the plugin](#installing-the-plugin)
12+
- [Using yarn](#using-yarn)
13+
- [Or using NPM](#or-using-npm)
14+
- [Setting up the plugin](#setting-up-the-plugin)
1215
- [Basic usage](#basic-usage)
1316
- [Advanced usage](#advanced-usage)
1417
- [Deep queries populate](#deep-queries-populate)
@@ -17,7 +20,14 @@ Source plugin for pulling documents into Gatsby from a Strapi API.
1720
- [Rich text field](#rich-text-field)
1821
- [Components](#components)
1922
- [Dynamic zones](#dynamic-zones)
23+
- [Internationalization](#internationalization)
2024
- [Gatsby cloud and preview environment setup](#gatsby-cloud-and-preview-environment-setup)
25+
- [Setup](#setup)
26+
- [Enabling Content Sync](#enabling-content-sync)
27+
- [Installing the @strapi/plugin-gatsby-preview](#installing-the-strapiplugin-gatsby-preview)
28+
- [Using yarn](#using-yarn-1)
29+
- [Using npm](#using-npm)
30+
- [Configurations](#configurations)
2131
- [Restrictions and limitations](#restrictions-and-limitations)
2232

2333
</details>
@@ -42,7 +52,7 @@ You can enable and configure this plugin in your `gatsby-config.js` file.
4252

4353
### Basic usage
4454

45-
First, you need to configure the `STRAPI_API_URL` and the `STRAPI_TOKEN` environment variables. We recommend using [`dotenv`][https://github.com/motdotla/dotenv] to expose these variables.
55+
First, you need to configure the `STRAPI_API_URL` and the `STRAPI_TOKEN` environment variables. We recommend using [`dotenv`](https://github.com/motdotla/dotenv) to expose these variables.
4656

4757
Make sure to create a full-access [API token](https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/api-tokens.html) in Strapi.
4858

@@ -248,7 +258,7 @@ To query a specific component use the following query:
248258

249259
#### Dynamic zones
250260

251-
To query dynamic zones, , write a query using [inline GraphQL fragments](https://graphql.org/learn/queries/#inline-fragments).
261+
To query dynamic zones, write a query using [inline GraphQL fragments](https://graphql.org/learn/queries/#inline-fragments).
252262

253263
You can use the following query:
254264

@@ -280,6 +290,62 @@ You can use the following query:
280290
}
281291
```
282292

293+
#### Internationalization
294+
295+
Content types in Strapi can be localized with the [i18n plugin](https://docs.strapi.io/developer-docs/latest/plugins/i18n.html). But by default, gatsby-source-strapi will only fetch data in the default locale of your Strapi app. To specify which locale should be fetched, an `i18n` object can be provided in the content type's `pluginOptions`. You can also set the locale to `all` to get all available localizations of a content type:
296+
297+
```javascript
298+
const strapiConfig = {
299+
// ...
300+
collectionTypes: [
301+
{
302+
singularName: 'article',
303+
pluginOptions: {
304+
i18n: {
305+
locale: 'fr', // Only fetch a specific locale
306+
},
307+
},
308+
},
309+
],
310+
singleTypes: [
311+
{
312+
singularName: 'global',
313+
pluginOptions: {
314+
i18n: {
315+
locale: 'all', // Fetch all localizations
316+
},
317+
},
318+
},
319+
],
320+
// ...
321+
};
322+
```
323+
324+
Then use the one of the following queries to fetch a localized content type:
325+
326+
```graphql
327+
{
328+
# Get content in all available localizations
329+
allStrapiGlobal {
330+
nodes {
331+
locale
332+
}
333+
}
334+
335+
# Get a single type in a specific locale
336+
strapiGlobal(locale: {eq: "fr"}) {
337+
locale
338+
}
339+
340+
# Get a collection type in a specific locale
341+
allStrapiArticle(filter: {locale: {eq: "fr"}}) {
342+
nodes {
343+
locale
344+
}
345+
}
346+
}
347+
```
348+
283349
## Gatsby cloud and preview environment setup
284350

285351
### Setup

src/fetch.js

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import createInstance from './axiosInstance';
33
import qs from 'qs';
44
import { cleanData } from './clean-data';
55

6-
const fetchStrapiContentTypes = async (pluginOptions) => {
7-
const axiosInstance = createInstance(pluginOptions);
6+
const fetchStrapiContentTypes = async (strapiConfig) => {
7+
const axiosInstance = createInstance(strapiConfig);
88
const [
99
{
1010
data: { data: contentTypes },
@@ -24,7 +24,7 @@ const fetchStrapiContentTypes = async (pluginOptions) => {
2424
};
2525
};
2626

27-
const fetchEntity = async ({ endpoint, queryParams, uid }, ctx) => {
27+
const fetchEntity = async ({ endpoint, queryParams, uid, pluginOptions }, ctx) => {
2828
const { strapiConfig, reporter } = ctx;
2929
const axiosInstance = createInstance(strapiConfig);
3030

@@ -38,9 +38,56 @@ const fetchEntity = async ({ endpoint, queryParams, uid }, ctx) => {
3838
try {
3939
reporter.info(`Starting to fetch data from Strapi - ${opts.url} with ${JSON.stringify(opts)}`);
4040

41+
// Handle internationalization
42+
const locale = pluginOptions?.i18n?.locale;
43+
const otherLocales = [];
44+
45+
if (locale) {
46+
// Ignore queryParams locale in favor of pluginOptions
47+
delete queryParams.locale;
48+
49+
if (locale === 'all') {
50+
// Get all available locales
51+
const { data: response } = await axiosInstance({
52+
...opts,
53+
params: {
54+
populate: {
55+
localizations: {
56+
fields: ['locale'],
57+
},
58+
},
59+
},
60+
});
61+
response.data.attributes.localizations.data.forEach((localization) =>
62+
otherLocales.push(localization.attributes.locale)
63+
);
64+
} else {
65+
// Only one locale
66+
queryParams.locale = locale;
67+
}
68+
}
69+
70+
// Fetch default entity based on request options
4171
const { data } = await axiosInstance(opts);
4272

43-
return castArray(data.data).map((entry) => cleanData(entry, { ...ctx, contentTypeUid: uid }));
73+
// Fetch other localizations of this entry if there are any
74+
const otherLocalizationsPromises = otherLocales.map(async (locale) => {
75+
const { data: localizationResponse } = await axiosInstance({
76+
...opts,
77+
params: {
78+
...opts.params,
79+
locale,
80+
},
81+
});
82+
return localizationResponse.data;
83+
});
84+
85+
// Run queries in parallel
86+
const otherLocalizationsData = await Promise.all(otherLocalizationsPromises);
87+
88+
return castArray([data.data, ...otherLocalizationsData]).map((entry) =>
89+
cleanData(entry, { ...ctx, contentTypeUid: uid })
90+
);
4491
} catch (error) {
4592
// reporter.panic(
4693
// `Failed to fetch data from Strapi ${opts.url} with ${JSON.stringify(opts)}`,
@@ -50,7 +97,7 @@ const fetchEntity = async ({ endpoint, queryParams, uid }, ctx) => {
5097
}
5198
};
5299

53-
const fetchEntities = async ({ endpoint, queryParams, uid }, ctx) => {
100+
const fetchEntities = async ({ endpoint, queryParams, uid, pluginOptions }, ctx) => {
54101
const { strapiConfig, reporter } = ctx;
55102
const axiosInstance = createInstance(strapiConfig);
56103

@@ -61,6 +108,12 @@ const fetchEntities = async ({ endpoint, queryParams, uid }, ctx) => {
61108
paramsSerializer: (params) => qs.stringify(params, { encodeValuesOnly: true }),
62109
};
63110

111+
// Use locale from pluginOptions if it's defined
112+
if (pluginOptions?.i18n?.locale) {
113+
delete queryParams.locale;
114+
queryParams.locale = pluginOptions.i18n.locale;
115+
}
116+
64117
try {
65118
reporter.info(
66119
`Starting to fetch data from Strapi - ${opts.url} with ${JSON.stringify(opts.params)}`
@@ -78,7 +131,7 @@ const fetchEntities = async ({ endpoint, queryParams, uid }, ctx) => {
78131
length: pageCount - page,
79132
}).map((_, i) => i + page + 1);
80133

81-
const arrayOfPromises = pagesToGet.map((page) => {
134+
const fetchPagesPromises = pagesToGet.map((page) => {
82135
return (async () => {
83136
const options = {
84137
...opts,
@@ -104,7 +157,7 @@ const fetchEntities = async ({ endpoint, queryParams, uid }, ctx) => {
104157
})();
105158
});
106159

107-
const results = await Promise.all(arrayOfPromises);
160+
const results = await Promise.all(fetchPagesPromises);
108161

109162
const cleanedData = [...data, ...flattenDeep(results)].map((entry) =>
110163
cleanData(entry, { ...ctx, contentTypeUid: uid })

src/gatsby-node.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,22 @@ exports.sourceNodes = async (
2424
getNodes,
2525
getNode,
2626
},
27-
pluginOptions
27+
strapiConfig
2828
) => {
2929
// Cast singleTypes and collectionTypes to empty arrays if they're not defined
30-
if (!Array.isArray(pluginOptions.singleTypes)) {
31-
pluginOptions.singleTypes = [];
30+
if (!Array.isArray(strapiConfig.singleTypes)) {
31+
strapiConfig.singleTypes = [];
3232
}
33-
if (!Array.isArray(pluginOptions.collectionTypes)) {
34-
pluginOptions.collectionTypes = [];
33+
if (!Array.isArray(strapiConfig.collectionTypes)) {
34+
strapiConfig.collectionTypes = [];
3535
}
3636

37-
const { schemas } = await fetchStrapiContentTypes(pluginOptions);
37+
const { schemas } = await fetchStrapiContentTypes(strapiConfig);
3838

3939
const { deleteNode, touchNode } = actions;
4040

4141
const ctx = {
42-
strapiConfig: pluginOptions,
42+
strapiConfig,
4343
actions,
4444
schemas,
4545
createContentDigest,
@@ -58,7 +58,7 @@ exports.sourceNodes = async (
5858

5959
existingNodes.forEach((n) => touchNode(n));
6060

61-
const endpoints = getEndpoints(pluginOptions, schemas);
61+
const endpoints = getEndpoints(strapiConfig, schemas);
6262

6363
const lastFetched = await cache.get(LAST_FETCHED_KEY);
6464

src/helpers.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ const getEndpoints = ({ collectionTypes, singleTypes }, schemas) => {
9999
)
100100
.map(({ schema: { kind, singularName, pluralName }, uid }) => {
101101
const options = types.find((config) => config.singularName === singularName);
102-
const { queryParams, queryLimit } = options;
102+
const { queryParams, queryLimit, pluginOptions } = options;
103103

104104
if (kind === 'singleType') {
105105
return {
@@ -110,6 +110,7 @@ const getEndpoints = ({ collectionTypes, singleTypes }, schemas) => {
110110
queryParams: queryParams || {
111111
populate: '*',
112112
},
113+
pluginOptions,
113114
};
114115
}
115116

@@ -127,6 +128,7 @@ const getEndpoints = ({ collectionTypes, singleTypes }, schemas) => {
127128
},
128129
populate: queryParams?.populate || '*',
129130
},
131+
pluginOptions,
130132
};
131133
});
132134

0 commit comments

Comments
 (0)