@littlebox/strapi-suite 1.0.30 → 1.0.31

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/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  - **Sitemap**: a way to set the properties to generate the sitemap.
7
7
  - **Page attributes**: a way to set page properties like templates or parent pages to automatically create full slugs.
8
8
  - **Parameters**: effortlessly manage and customize settings with a intuitive and flexible solution.
9
+
9
10
   
10
11
   
11
12
   
@@ -20,6 +21,7 @@ yarn add @littlebox/strapi-suite
20
21
  # using npm
21
22
  npm install @littlebox/strapi-suite --save
22
23
  ```
24
+
23
25
   
24
26
   
25
27
   
@@ -30,6 +32,7 @@ The full installation requirements are identical to those of Strapi and can be f
30
32
  **Supported Strapi versions**:
31
33
 
32
34
  - Strapi ^5.0.0
35
+
33
36
   
34
37
   
35
38
   
@@ -162,10 +165,12 @@ Optimize URLs with smart, SEO-friendly slugs for better rankings and cleaner lin
162
165
 
163
166
  ![Slug custom field](https://github.com/littleboxstudio/strapi-suite/blob/main/docs/screenshots/slug-custom-field.png?raw=true)
164
167
 
168
+ ![Slug settings](https://github.com/littleboxstudio/strapi-suite/blob/main/docs/screenshots/slug-settings.png?raw=true)
169
+
165
170
  This lets you get data from a document (either a collection or single content) using the slug. To get the data from the frontend, use your preferred HTTP client:
166
171
 
167
172
  ```
168
- GET /api/littlebox-strapi-suite/modules/pages?slug=<SLUG>&locale=<LOCALE>
173
+ GET /api/littlebox-strapi-suite/modules/pages?slug=<SLUG>
169
174
  ```
170
175
  ```
171
176
  {
@@ -183,7 +188,7 @@ GET /api/littlebox-strapi-suite/modules/pages?slug=<SLUG>&locale=<LOCALE>
183
188
  "id": 27,
184
189
  "documentId": "i111r5p3pa73r6tm71b7lh86",
185
190
  "title": "Littlebox Suite ajudou-me a construir sites mais rápido",
186
- "slug": "noticias/littlebox-suite-ajudou-me-a-construir-sites-mais-rapido",
191
+ "slug": "pt/noticias/littlebox-suite-ajudou-me-a-construir-sites-mais-rapido",
187
192
  "createdAt": "2025-04-13T21:37:55.693Z",
188
193
  "updatedAt": "2025-04-13T22:05:35.160Z",
189
194
  "publishedAt": "2025-04-13T22:05:35.185Z",
@@ -193,6 +198,7 @@ GET /api/littlebox-strapi-suite/modules/pages?slug=<SLUG>&locale=<LOCALE>
193
198
  }
194
199
  }
195
200
  ```
201
+ **Note**: The default language won't show up in the URL slug if the `SHOW LANGUAGE SLUG` setting is turned off in the slug module settings (see screenshot above).
196
202
 
197
203
  &nbsp;
198
204
  &nbsp;
@@ -209,7 +215,7 @@ A way to set page properties like templates or parent pages to automatically cre
209
215
  To get the data from the frontend, use your preferred HTTP client:
210
216
 
211
217
  ```
212
- GET /api/littlebox-strapi-suite/modules/pages?slug=<SLUG>&locale=<LOCALE>&properties=attributes
218
+ GET /api/littlebox-strapi-suite/modules/pages?slug=<SLUG>&properties=attributes
213
219
  ```
214
220
  ```
215
221
  {
@@ -227,7 +233,7 @@ GET /api/littlebox-strapi-suite/modules/pages?slug=<SLUG>&locale=<LOCALE>&proper
227
233
  "id": 27,
228
234
  "documentId": "i111r5p3pa73r6tm71b7lh86",
229
235
  "title": "Littlebox Suite ajudou-me a construir sites mais rápido",
230
- "slug": "noticias/littlebox-suite-ajudou-me-a-construir-sites-mais-rapido",
236
+ "slug": "pt/noticias/littlebox-suite-ajudou-me-a-construir-sites-mais-rapido",
231
237
  "createdAt": "2025-04-13T21:37:55.693Z",
232
238
  "updatedAt": "2025-04-13T22:05:35.160Z",
233
239
  "publishedAt": "2025-04-13T22:05:35.185Z",
@@ -263,27 +269,53 @@ GET /api/littlebox-strapi-suite/modules/pages?properties=attributes
263
269
  "id": "wnzxub0s3ghckznjdkshgcw7",
264
270
  "model": "api::page.page",
265
271
  "slug": "news",
266
- "locale": "en"
272
+ "locale": "en",
273
+ "attributes": {
274
+ "template": "default",
275
+ "priority": "1.0",
276
+ "frequency": "weekly"
277
+ }
267
278
  },
268
279
  {
269
280
  "id": "wnzxub0s3ghckznjdkshgcw7",
270
281
  "model": "api::page.page",
271
282
  "slug": "noticias",
272
- "locale": "pt"
283
+ "locale": "pt",
284
+ "attributes": {
285
+ "template": "default",
286
+ "priority": "1.0",
287
+ "frequency": "weekly"
288
+ }
273
289
  },
274
290
  {
275
291
  "id": "i111r5p3pa73r6tm71b7lh86",
276
292
  "model": "api::page.page",
277
293
  "slug": "news/littlebox-suite-helped-me-build-websites-faster",
278
294
  "locale": "en",
279
- "parentId": "wnzxub0s3ghckznjdkshgcw7"
295
+ "attributes": {
296
+ "template": "default",
297
+ "priority": "1.0",
298
+ "frequency": "yearly",
299
+ "parent": {
300
+ "id": "wnzxub0s3ghckznjdkshgcw7",
301
+ "model": "api::page.page"
302
+ }
303
+ }
280
304
  },
281
305
  {
282
306
  "id": "i111r5p3pa73r6tm71b7lh86",
283
307
  "model": "api::page.page",
284
- "slug": "noticias/littlebox-suite-ajudou-me-a-construir-sites-mais-rapido",
308
+ "slug": "pt/noticias/littlebox-suite-ajudou-me-a-construir-sites-mais-rapido",
285
309
  "locale": "pt",
286
- parentId: "wnzxub0s3ghckznjdkshgcw7"
310
+ "attributes": {
311
+ "template": "default",
312
+ "priority": "1.0",
313
+ "frequency": "yearly",
314
+ "parent": {
315
+ "id": "wnzxub0s3ghckznjdkshgcw7",
316
+ "model": "api::page.page"
317
+ }
318
+ }
287
319
  }
288
320
  ]
289
321
  ```
@@ -303,7 +335,21 @@ Effortlessly manage and customize settings with a intuitive and flexible solutio
303
335
  To get the data from the frontend, use your preferred HTTP client:
304
336
 
305
337
  ```
306
- GET /api/littlebox-strapi-suite/modules/pages?slug=<SLUG>&locale=<LOCALE>&properties=attributes
338
+ GET /api/littlebox-strapi-suite/modules/parameters
339
+ ```
340
+ ```
341
+ [
342
+ {
343
+ "uid": "recaptcha-public-key",
344
+ "value": "iuyTYYT7ybknokdiuYTtdjapodu"
345
+ }
346
+ ]
347
+ ```
348
+ This request will only return public parameters. To get the private parameters from the Strapi backend (e.g. for use in other plugins), use the `@strapi/strapi/admin` library:
349
+ ```
350
+ import { getFetchClient } from '@strapi/strapi/admin';
351
+ const { get } = getFetchClient();
352
+ const data = await get('/littlebox-strapi-suite/admin/parameters');
307
353
  ```
308
354
 
309
355
  &nbsp;
@@ -4,12 +4,12 @@ const jsxRuntime = require("react/jsx-runtime");
4
4
  const reactRouterDom = require("react-router-dom");
5
5
  const React = require("react");
6
6
  const designSystem = require("@strapi/design-system");
7
- const index = require("./index-BW7xqYof.js");
7
+ const index = require("./index-BZqSioMv.js");
8
8
  const icons = require("@strapi/icons");
9
9
  const reactIntl = require("react-intl");
10
10
  const styled = require("styled-components");
11
11
  const symbols = require("@strapi/icons/symbols");
12
- const convertToSlug = require("./convertToSlug-B5DOR_Nr.js");
12
+ const convertToSlug = require("./convertToSlug-DGSdTBaK.js");
13
13
  const core = require("@dnd-kit/core");
14
14
  const sortable = require("@dnd-kit/sortable");
15
15
  const modifiers = require("@dnd-kit/modifiers");
@@ -931,7 +931,7 @@ const ConfirmModal = ({ open, title, text, confirm, cancel }) => {
931
931
  ] }) }) });
932
932
  };
933
933
  const SlugSettingsModal = ({ open, close }) => {
934
- const [module2, setModule] = React.useState(index.config.uuid.modules.menu);
934
+ const [module2, setModule] = React.useState(index.config.uuid.modules.slug);
935
935
  const [hidden, setHidden] = React.useState(true);
936
936
  const [checked, setChecked] = React.useState(true);
937
937
  const { formatMessage } = reactIntl.useIntl();
@@ -2,12 +2,12 @@ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { useNavigate, useParams, Routes, Route } from "react-router-dom";
3
3
  import React__default, { useState, useEffect, createContext, useContext, Fragment as Fragment$1, useRef } from "react";
4
4
  import { Box, Loader, Main, Typography, Button, Flex, Breadcrumbs, Crumb, CrumbLink, CardBody, CardContent, CardTitle, CardBadge, CardSubtitle, Card as Card$1, Dialog, IconButton, Toggle, SearchForm, Searchbar, SingleSelect, SingleSelectOption, Table, Thead, Tr, Th, Checkbox, VisuallyHidden, Tbody, Td, EmptyStateLayout, TextInput, Field, Tooltip } from "@strapi/design-system";
5
- import { R as Registry, F as FetchSettings, g as getTranslation, c as config, a as FetchSlugs, f as fetchTemplates } from "./index-B-VDYXwv.mjs";
5
+ import { R as Registry, F as FetchSettings, g as getTranslation, c as config, a as FetchSlugs, f as fetchTemplates } from "./index-BBTYu57z.mjs";
6
6
  import { ArrowLeft, ExternalLink, WarningCircle, Cross, BulletList, Pencil, Trash, Plus, Duplicate, Drag, Check } from "@strapi/icons";
7
7
  import { useIntl } from "react-intl";
8
8
  import styled, { useTheme } from "styled-components";
9
9
  import { EmptyDocuments } from "@strapi/icons/symbols";
10
- import { F as FetchLocales, c as convertToSlug } from "./convertToSlug-CmCb9ke3.mjs";
10
+ import { F as FetchLocales, c as convertToSlug } from "./convertToSlug-CRnBMJHB.mjs";
11
11
  import { DndContext, DragOverlay, pointerWithin, rectIntersection } from "@dnd-kit/core";
12
12
  import { useSortable, SortableContext, verticalListSortingStrategy, arrayMove } from "@dnd-kit/sortable";
13
13
  import { restrictToVerticalAxis, restrictToParentElement } from "@dnd-kit/modifiers";
@@ -926,7 +926,7 @@ const ConfirmModal = ({ open, title, text, confirm, cancel }) => {
926
926
  ] }) }) });
927
927
  };
928
928
  const SlugSettingsModal = ({ open, close }) => {
929
- const [module, setModule] = useState(config.uuid.modules.menu);
929
+ const [module, setModule] = useState(config.uuid.modules.slug);
930
930
  const [hidden, setHidden] = useState(true);
931
931
  const [checked, setChecked] = useState(true);
932
932
  const { formatMessage } = useIntl();
@@ -8,8 +8,8 @@ const designSystem = require("@strapi/design-system");
8
8
  const icons = require("@strapi/icons");
9
9
  const admin = require("@strapi/strapi/admin");
10
10
  const styled = require("styled-components");
11
- const index = require("./index-BW7xqYof.js");
12
- const convertToSlug = require("./convertToSlug-B5DOR_Nr.js");
11
+ const index = require("./index-BZqSioMv.js");
12
+ const convertToSlug = require("./convertToSlug-DGSdTBaK.js");
13
13
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
14
14
  function _interopNamespace(e) {
15
15
  if (e && e.__esModule) return e;
@@ -6,8 +6,8 @@ import { useComposedRefs, Field, Box, Typography, TextInput, IconButton, Button
6
6
  import { Pin, Cross } from "@strapi/icons";
7
7
  import { useFocusInputField, unstable_useContentManagerContext } from "@strapi/strapi/admin";
8
8
  import styled from "styled-components";
9
- import { R as Registry, P as PageAttributeUpdated, D as DocumentCustomFieldStarted, b as PluginIcon, g as getTranslation, c as config, d as FetchModuleSettings } from "./index-B-VDYXwv.mjs";
10
- import { c as convertToSlug, F as FetchLocales } from "./convertToSlug-CmCb9ke3.mjs";
9
+ import { R as Registry, P as PageAttributeUpdated, D as DocumentCustomFieldStarted, b as PluginIcon, g as getTranslation, c as config, d as FetchModuleSettings } from "./index-BBTYu57z.mjs";
10
+ import { c as convertToSlug, F as FetchLocales } from "./convertToSlug-CRnBMJHB.mjs";
11
11
  const BoxInput = styled(Box)`
12
12
  & > div {
13
13
  width: 100%;
@@ -1,4 +1,4 @@
1
- import { R as Registry } from "./index-B-VDYXwv.mjs";
1
+ import { R as Registry } from "./index-BBTYu57z.mjs";
2
2
  class FetchLocales {
3
3
  localeGateway;
4
4
  constructor() {
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const index = require("./index-BW7xqYof.js");
2
+ const index = require("./index-BZqSioMv.js");
3
3
  class FetchLocales {
4
4
  localeGateway;
5
5
  constructor() {
@@ -3301,7 +3301,7 @@ const index = {
3301
3301
  defaultMessage: config.pluginId
3302
3302
  },
3303
3303
  position: 999,
3304
- Component: () => import("./App-5t0oXrfw.mjs")
3304
+ Component: () => import("./App-CXitaGLI.mjs")
3305
3305
  });
3306
3306
  app.customFields.register({
3307
3307
  name: "ltbslug",
@@ -3319,7 +3319,7 @@ const index = {
3319
3319
  components: {
3320
3320
  Input: async () => import(
3321
3321
  /* webpackChunkName: "input-slug-component" */
3322
- "./SlugInput-C221apIK.mjs"
3322
+ "./SlugInput-DvuzCwKx.mjs"
3323
3323
  )
3324
3324
  },
3325
3325
  options: {
@@ -3304,7 +3304,7 @@ const index = {
3304
3304
  defaultMessage: config.pluginId
3305
3305
  },
3306
3306
  position: 999,
3307
- Component: () => Promise.resolve().then(() => require("./App-DUrW4zBW.js"))
3307
+ Component: () => Promise.resolve().then(() => require("./App-BwtvAoMl.js"))
3308
3308
  });
3309
3309
  app.customFields.register({
3310
3310
  name: "ltbslug",
@@ -3322,7 +3322,7 @@ const index = {
3322
3322
  components: {
3323
3323
  Input: async () => Promise.resolve().then(() => require(
3324
3324
  /* webpackChunkName: "input-slug-component" */
3325
- "./SlugInput-CxxShxb6.js"
3325
+ "./SlugInput-0Vo-U5cA.js"
3326
3326
  ))
3327
3327
  },
3328
3328
  options: {
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
- const index = require("../_chunks/index-BW7xqYof.js");
2
+ const index = require("../_chunks/index-BZqSioMv.js");
3
3
  module.exports = index.index;
@@ -1,4 +1,4 @@
1
- import { i } from "../_chunks/index-B-VDYXwv.mjs";
1
+ import { i } from "../_chunks/index-BBTYu57z.mjs";
2
2
  export {
3
3
  i as default
4
4
  };
@@ -432,7 +432,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
432
432
  module: "slug",
433
433
  property: "showDefaultLanguage",
434
434
  type: "boolean",
435
- value: "true"
435
+ value: "false"
436
436
  },
437
437
  {
438
438
  module: "template",
@@ -1210,6 +1210,15 @@ const contentAPIRoutes = [
1210
1210
  policies: [],
1211
1211
  auth: false
1212
1212
  }
1213
+ },
1214
+ {
1215
+ method: "GET",
1216
+ path: "/modules/parameters",
1217
+ handler: "ParameterModuleController.getParameters",
1218
+ config: {
1219
+ policies: [],
1220
+ auth: false
1221
+ }
1213
1222
  }
1214
1223
  ];
1215
1224
  const adminAPIRoutes = [
@@ -1481,23 +1490,39 @@ async function getSlugByDocumentId(params) {
1481
1490
  const parentSlug = await getSlugByDocumentId({
1482
1491
  contentId: document.parentContentId,
1483
1492
  locale: params.locale,
1493
+ defaultLocale: params.defaultLocale,
1494
+ showDefaultLanguage: params.showDefaultLanguage,
1484
1495
  strapi: params.strapi
1485
1496
  });
1486
1497
  return `${parentSlug}/${document.slug}`;
1487
1498
  }
1488
- return document.slug;
1499
+ return params.showDefaultLanguage || !params.showDefaultLanguage && params.defaultLocale !== params.locale ? `${params.locale.toLowerCase()}/${document.slug}` : document.slug;
1489
1500
  }
1490
- function findItem(items, contentId, contentModel) {
1491
- return items.find(
1492
- (item) => item.contentId === contentId && item.contentModel === contentModel
1501
+ function findItem(params) {
1502
+ return params.pages.find(
1503
+ (page) => page.contentId === params.contentId && page.contentModel === params.contentModel && page.locale === params.locale
1493
1504
  );
1494
1505
  }
1495
- function buildFullSlug(items, item) {
1496
- if (!item.parentContentId || !item.parentContentModel) return item.slug;
1497
- const parent = findItem(items, item.parentContentId, item.parentContentModel);
1498
- if (!parent) return item.slug;
1499
- const parentFullSlug = parent.fullSlug || buildFullSlug(items, parent);
1500
- return `${parentFullSlug}/${item.slug}`;
1506
+ function buildFullSlug(params) {
1507
+ if (!params.page.parentContentId || !params.page.parentContentModel) {
1508
+ return params.showDefaultLanguage || !params.showDefaultLanguage && params.defaultLocale !== params.page.locale ? `${params.page.locale.toLowerCase()}/${params.page.slug}` : params.page.slug;
1509
+ }
1510
+ const parent = findItem({
1511
+ pages: params.pages,
1512
+ contentId: params.page.parentContentId,
1513
+ contentModel: params.page.parentContentModel,
1514
+ locale: params.page.locale
1515
+ });
1516
+ if (!parent) {
1517
+ return params.page.slug;
1518
+ }
1519
+ const parentFullSlug = parent.fullSlug || buildFullSlug({
1520
+ pages: params.pages,
1521
+ page: parent,
1522
+ defaultLocale: params.defaultLocale,
1523
+ showDefaultLanguage: params.showDefaultLanguage
1524
+ });
1525
+ return `${parentFullSlug}/${params.page.slug}`;
1501
1526
  }
1502
1527
  const SlugModuleService = ({ strapi: strapi2 }) => ({
1503
1528
  async adminGetAll() {
@@ -1544,21 +1569,24 @@ const SlugModuleService = ({ strapi: strapi2 }) => ({
1544
1569
  },
1545
1570
  async getPage() {
1546
1571
  const ctx = strapi2.requestContext.get();
1547
- if (!ctx.query.locale) {
1548
- ctx.status = 400;
1549
- return;
1550
- }
1551
1572
  const config2 = strapi2.config.get(`plugin::${PLUGIN_ID}`);
1552
1573
  const slug = ctx.query.slug.replace(/^\/|\/$/g, "");
1574
+ const defaultLocale = await strapi2.plugin("i18n").service("locales").getDefaultLocale();
1575
+ const setting = await strapi2.db.query(config2.uuid.app.setting).findOne({
1576
+ where: {
1577
+ module: "slug",
1578
+ property: "showDefaultLanguage"
1579
+ }
1580
+ });
1581
+ const showDefaultLanguage = setting.value === "true";
1553
1582
  const pages = await strapi2.db.query(config2.uuid.modules.slug).findMany({
1554
1583
  where: {
1555
1584
  state: "published",
1556
- locale: ctx.query.locale,
1557
1585
  slug: slug.split("/")
1558
1586
  }
1559
1587
  });
1560
- pages.forEach((item) => {
1561
- item.fullSlug = buildFullSlug(pages, item);
1588
+ pages.forEach((page2) => {
1589
+ page2.fullSlug = buildFullSlug({ pages, page: page2, defaultLocale, showDefaultLanguage });
1562
1590
  });
1563
1591
  const page = pages.find((page2) => page2.fullSlug === slug);
1564
1592
  if (!page) {
@@ -1569,7 +1597,7 @@ const SlugModuleService = ({ strapi: strapi2 }) => ({
1569
1597
  if (properties && properties.includes("attributes")) {
1570
1598
  const attributes2 = await strapi2.db.query(config2.uuid.modules.attribute).findOne({
1571
1599
  where: {
1572
- locale: ctx.query.locale,
1600
+ locale: page.locale,
1573
1601
  contentId: page.contentId,
1574
1602
  contentModel: page.contentModel,
1575
1603
  state: "published"
@@ -1588,14 +1616,17 @@ const SlugModuleService = ({ strapi: strapi2 }) => ({
1588
1616
  };
1589
1617
  }
1590
1618
  const document = await strapi2.documents(page.contentModel).findOne({
1591
- documentId: page.contentId,
1619
+ locale: page.locale,
1592
1620
  populate: "*",
1593
- status: "published"
1621
+ status: "published",
1622
+ documentId: page.contentId
1594
1623
  });
1595
1624
  for (const localization of document.localizations) {
1596
1625
  localization.slug = await getSlugByDocumentId({
1597
1626
  contentId: localization.documentId,
1598
1627
  locale: localization.locale,
1628
+ defaultLocale,
1629
+ showDefaultLanguage,
1599
1630
  strapi: strapi2
1600
1631
  });
1601
1632
  }
@@ -1611,13 +1642,21 @@ const SlugModuleService = ({ strapi: strapi2 }) => ({
1611
1642
  const ctx = strapi2.requestContext.get();
1612
1643
  const properties = ctx.query.properties;
1613
1644
  const config2 = strapi2.config.get(`plugin::${PLUGIN_ID}`);
1645
+ const defaultLocale = await strapi2.plugin("i18n").service("locales").getDefaultLocale();
1646
+ const setting = await strapi2.db.query(config2.uuid.app.setting).findOne({
1647
+ where: {
1648
+ module: "slug",
1649
+ property: "showDefaultLanguage"
1650
+ }
1651
+ });
1652
+ const showDefaultLanguage = setting.value === "true";
1614
1653
  const pages = await strapi2.db.query(config2.uuid.modules.slug).findMany({
1615
1654
  where: {
1616
1655
  state: "published"
1617
1656
  }
1618
1657
  });
1619
- pages.forEach((item) => {
1620
- item.fullSlug = buildFullSlug(pages, item);
1658
+ pages.forEach((page) => {
1659
+ page.fullSlug = buildFullSlug({ pages, page, defaultLocale, showDefaultLanguage });
1621
1660
  });
1622
1661
  if (properties && properties.includes("attributes")) {
1623
1662
  for (const page of pages) {
@@ -1646,6 +1685,7 @@ const SlugModuleService = ({ strapi: strapi2 }) => ({
1646
1685
  id: page.contentId,
1647
1686
  model: page.contentModel,
1648
1687
  slug: page.fullSlug,
1688
+ locale: page.locale,
1649
1689
  ...page.attributes ? { attributes: page.attributes } : {}
1650
1690
  }));
1651
1691
  return mappedPages;
@@ -2013,6 +2053,14 @@ const MenuModuleService = ({ strapi: strapi2 }) => ({
2013
2053
  return;
2014
2054
  }
2015
2055
  const config2 = strapi2.config.get(`plugin::${PLUGIN_ID}`);
2056
+ const defaultLocale = await strapi2.plugin("i18n").service("locales").getDefaultLocale();
2057
+ const setting = await strapi2.db.query(config2.uuid.app.setting).findOne({
2058
+ where: {
2059
+ module: "slug",
2060
+ property: "showDefaultLanguage"
2061
+ }
2062
+ });
2063
+ const showDefaultLanguage = setting.value === "true";
2016
2064
  const documents = await strapi2.db.query(config2.uuid.modules.menu.main).findMany({
2017
2065
  where: {
2018
2066
  locale: ctx.query.locale
@@ -2039,8 +2087,10 @@ const MenuModuleService = ({ strapi: strapi2 }) => ({
2039
2087
  });
2040
2088
  if (content) {
2041
2089
  child.url = await getSlugByDocumentId({
2042
- locale,
2043
2090
  contentId: child.contentId,
2091
+ defaultLocale,
2092
+ showDefaultLanguage,
2093
+ locale,
2044
2094
  strapi: strapi2
2045
2095
  });
2046
2096
  }
@@ -431,7 +431,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
431
431
  module: "slug",
432
432
  property: "showDefaultLanguage",
433
433
  type: "boolean",
434
- value: "true"
434
+ value: "false"
435
435
  },
436
436
  {
437
437
  module: "template",
@@ -1209,6 +1209,15 @@ const contentAPIRoutes = [
1209
1209
  policies: [],
1210
1210
  auth: false
1211
1211
  }
1212
+ },
1213
+ {
1214
+ method: "GET",
1215
+ path: "/modules/parameters",
1216
+ handler: "ParameterModuleController.getParameters",
1217
+ config: {
1218
+ policies: [],
1219
+ auth: false
1220
+ }
1212
1221
  }
1213
1222
  ];
1214
1223
  const adminAPIRoutes = [
@@ -1480,23 +1489,39 @@ async function getSlugByDocumentId(params) {
1480
1489
  const parentSlug = await getSlugByDocumentId({
1481
1490
  contentId: document.parentContentId,
1482
1491
  locale: params.locale,
1492
+ defaultLocale: params.defaultLocale,
1493
+ showDefaultLanguage: params.showDefaultLanguage,
1483
1494
  strapi: params.strapi
1484
1495
  });
1485
1496
  return `${parentSlug}/${document.slug}`;
1486
1497
  }
1487
- return document.slug;
1498
+ return params.showDefaultLanguage || !params.showDefaultLanguage && params.defaultLocale !== params.locale ? `${params.locale.toLowerCase()}/${document.slug}` : document.slug;
1488
1499
  }
1489
- function findItem(items, contentId, contentModel) {
1490
- return items.find(
1491
- (item) => item.contentId === contentId && item.contentModel === contentModel
1500
+ function findItem(params) {
1501
+ return params.pages.find(
1502
+ (page) => page.contentId === params.contentId && page.contentModel === params.contentModel && page.locale === params.locale
1492
1503
  );
1493
1504
  }
1494
- function buildFullSlug(items, item) {
1495
- if (!item.parentContentId || !item.parentContentModel) return item.slug;
1496
- const parent = findItem(items, item.parentContentId, item.parentContentModel);
1497
- if (!parent) return item.slug;
1498
- const parentFullSlug = parent.fullSlug || buildFullSlug(items, parent);
1499
- return `${parentFullSlug}/${item.slug}`;
1505
+ function buildFullSlug(params) {
1506
+ if (!params.page.parentContentId || !params.page.parentContentModel) {
1507
+ return params.showDefaultLanguage || !params.showDefaultLanguage && params.defaultLocale !== params.page.locale ? `${params.page.locale.toLowerCase()}/${params.page.slug}` : params.page.slug;
1508
+ }
1509
+ const parent = findItem({
1510
+ pages: params.pages,
1511
+ contentId: params.page.parentContentId,
1512
+ contentModel: params.page.parentContentModel,
1513
+ locale: params.page.locale
1514
+ });
1515
+ if (!parent) {
1516
+ return params.page.slug;
1517
+ }
1518
+ const parentFullSlug = parent.fullSlug || buildFullSlug({
1519
+ pages: params.pages,
1520
+ page: parent,
1521
+ defaultLocale: params.defaultLocale,
1522
+ showDefaultLanguage: params.showDefaultLanguage
1523
+ });
1524
+ return `${parentFullSlug}/${params.page.slug}`;
1500
1525
  }
1501
1526
  const SlugModuleService = ({ strapi: strapi2 }) => ({
1502
1527
  async adminGetAll() {
@@ -1543,21 +1568,24 @@ const SlugModuleService = ({ strapi: strapi2 }) => ({
1543
1568
  },
1544
1569
  async getPage() {
1545
1570
  const ctx = strapi2.requestContext.get();
1546
- if (!ctx.query.locale) {
1547
- ctx.status = 400;
1548
- return;
1549
- }
1550
1571
  const config2 = strapi2.config.get(`plugin::${PLUGIN_ID}`);
1551
1572
  const slug = ctx.query.slug.replace(/^\/|\/$/g, "");
1573
+ const defaultLocale = await strapi2.plugin("i18n").service("locales").getDefaultLocale();
1574
+ const setting = await strapi2.db.query(config2.uuid.app.setting).findOne({
1575
+ where: {
1576
+ module: "slug",
1577
+ property: "showDefaultLanguage"
1578
+ }
1579
+ });
1580
+ const showDefaultLanguage = setting.value === "true";
1552
1581
  const pages = await strapi2.db.query(config2.uuid.modules.slug).findMany({
1553
1582
  where: {
1554
1583
  state: "published",
1555
- locale: ctx.query.locale,
1556
1584
  slug: slug.split("/")
1557
1585
  }
1558
1586
  });
1559
- pages.forEach((item) => {
1560
- item.fullSlug = buildFullSlug(pages, item);
1587
+ pages.forEach((page2) => {
1588
+ page2.fullSlug = buildFullSlug({ pages, page: page2, defaultLocale, showDefaultLanguage });
1561
1589
  });
1562
1590
  const page = pages.find((page2) => page2.fullSlug === slug);
1563
1591
  if (!page) {
@@ -1568,7 +1596,7 @@ const SlugModuleService = ({ strapi: strapi2 }) => ({
1568
1596
  if (properties && properties.includes("attributes")) {
1569
1597
  const attributes2 = await strapi2.db.query(config2.uuid.modules.attribute).findOne({
1570
1598
  where: {
1571
- locale: ctx.query.locale,
1599
+ locale: page.locale,
1572
1600
  contentId: page.contentId,
1573
1601
  contentModel: page.contentModel,
1574
1602
  state: "published"
@@ -1587,14 +1615,17 @@ const SlugModuleService = ({ strapi: strapi2 }) => ({
1587
1615
  };
1588
1616
  }
1589
1617
  const document = await strapi2.documents(page.contentModel).findOne({
1590
- documentId: page.contentId,
1618
+ locale: page.locale,
1591
1619
  populate: "*",
1592
- status: "published"
1620
+ status: "published",
1621
+ documentId: page.contentId
1593
1622
  });
1594
1623
  for (const localization of document.localizations) {
1595
1624
  localization.slug = await getSlugByDocumentId({
1596
1625
  contentId: localization.documentId,
1597
1626
  locale: localization.locale,
1627
+ defaultLocale,
1628
+ showDefaultLanguage,
1598
1629
  strapi: strapi2
1599
1630
  });
1600
1631
  }
@@ -1610,13 +1641,21 @@ const SlugModuleService = ({ strapi: strapi2 }) => ({
1610
1641
  const ctx = strapi2.requestContext.get();
1611
1642
  const properties = ctx.query.properties;
1612
1643
  const config2 = strapi2.config.get(`plugin::${PLUGIN_ID}`);
1644
+ const defaultLocale = await strapi2.plugin("i18n").service("locales").getDefaultLocale();
1645
+ const setting = await strapi2.db.query(config2.uuid.app.setting).findOne({
1646
+ where: {
1647
+ module: "slug",
1648
+ property: "showDefaultLanguage"
1649
+ }
1650
+ });
1651
+ const showDefaultLanguage = setting.value === "true";
1613
1652
  const pages = await strapi2.db.query(config2.uuid.modules.slug).findMany({
1614
1653
  where: {
1615
1654
  state: "published"
1616
1655
  }
1617
1656
  });
1618
- pages.forEach((item) => {
1619
- item.fullSlug = buildFullSlug(pages, item);
1657
+ pages.forEach((page) => {
1658
+ page.fullSlug = buildFullSlug({ pages, page, defaultLocale, showDefaultLanguage });
1620
1659
  });
1621
1660
  if (properties && properties.includes("attributes")) {
1622
1661
  for (const page of pages) {
@@ -1645,6 +1684,7 @@ const SlugModuleService = ({ strapi: strapi2 }) => ({
1645
1684
  id: page.contentId,
1646
1685
  model: page.contentModel,
1647
1686
  slug: page.fullSlug,
1687
+ locale: page.locale,
1648
1688
  ...page.attributes ? { attributes: page.attributes } : {}
1649
1689
  }));
1650
1690
  return mappedPages;
@@ -2012,6 +2052,14 @@ const MenuModuleService = ({ strapi: strapi2 }) => ({
2012
2052
  return;
2013
2053
  }
2014
2054
  const config2 = strapi2.config.get(`plugin::${PLUGIN_ID}`);
2055
+ const defaultLocale = await strapi2.plugin("i18n").service("locales").getDefaultLocale();
2056
+ const setting = await strapi2.db.query(config2.uuid.app.setting).findOne({
2057
+ where: {
2058
+ module: "slug",
2059
+ property: "showDefaultLanguage"
2060
+ }
2061
+ });
2062
+ const showDefaultLanguage = setting.value === "true";
2015
2063
  const documents = await strapi2.db.query(config2.uuid.modules.menu.main).findMany({
2016
2064
  where: {
2017
2065
  locale: ctx.query.locale
@@ -2038,8 +2086,10 @@ const MenuModuleService = ({ strapi: strapi2 }) => ({
2038
2086
  });
2039
2087
  if (content) {
2040
2088
  child.url = await getSlugByDocumentId({
2041
- locale,
2042
2089
  contentId: child.contentId,
2090
+ defaultLocale,
2091
+ showDefaultLanguage,
2092
+ locale,
2043
2093
  strapi: strapi2
2044
2094
  });
2045
2095
  }
@@ -148,6 +148,7 @@ declare const _default: {
148
148
  id: any;
149
149
  model: any;
150
150
  slug: any;
151
+ locale: any;
151
152
  }[]>;
152
153
  };
153
154
  AttributeModuleService: ({ strapi }: {
@@ -20,6 +20,7 @@ declare const _default: {
20
20
  id: any;
21
21
  model: any;
22
22
  slug: any;
23
+ locale: any;
23
24
  }[]>;
24
25
  };
25
26
  AttributeModuleService: ({ strapi }: {
@@ -13,6 +13,7 @@ declare const SlugModuleService: ({ strapi }: {
13
13
  id: any;
14
14
  model: any;
15
15
  slug: any;
16
+ locale: any;
16
17
  }[]>;
17
18
  };
18
19
  export default SlugModuleService;
@@ -2,6 +2,8 @@ import type { Core } from '@strapi/strapi';
2
2
  declare function getSlugByDocumentId(params: {
3
3
  contentId: string;
4
4
  locale: string;
5
+ defaultLocale: string;
6
+ showDefaultLanguage: boolean;
5
7
  strapi: Core.Strapi;
6
8
  }): any;
7
9
  export { getSlugByDocumentId };
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.30",
2
+ "version": "1.0.31",
3
3
  "keywords": [
4
4
  "strapi",
5
5
  "strapi plugin",