@mapomodule/i18n 2.0.0-beta.2

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 ADDED
@@ -0,0 +1,62 @@
1
+ # @mapomodule/i18n
2
+
3
+ Mapo internationalization module. Wraps [`@nuxtjs/i18n`](https://i18n.nuxtjs.org) and ships the built-in UI translations for every Mapo component (English and Italian) under the `mapo.*` key namespace.
4
+
5
+ Installed automatically by the [`mapomodule`](../../mapomodule/) meta-package — you rarely need to add it yourself.
6
+
7
+ ## What it does
8
+
9
+ - Installs `@nuxtjs/i18n` with admin-friendly defaults: `no_prefix` strategy, browser language detection, cookie persistence, `fallbackLocale` = `defaultLocale`.
10
+ - Registers Mapo's message catalogs (`en`, `it`) via the `i18n:registerModule` hook.
11
+ - If the consuming app already declares `@nuxtjs/i18n` in `modules[]`, the app's configuration wins and this module only contributes the Mapo catalogs.
12
+
13
+ ## Configuration
14
+
15
+ ```ts
16
+ // nuxt.config.ts — through the meta-package
17
+ export default defineNuxtConfig({
18
+ modules: ["@nuxt/ui", "mapomodule"],
19
+ mapo: {
20
+ i18n: {
21
+ defaultLocale: "it",
22
+ },
23
+ },
24
+ });
25
+ ```
26
+
27
+ Or standalone under the `mapoI18n` key:
28
+
29
+ ```ts
30
+ export default defineNuxtConfig({
31
+ modules: ["@mapomodule/i18n"],
32
+ mapoI18n: {
33
+ defaultLocale: "en",
34
+ locales: [
35
+ { code: "en", language: "en-US", name: "English" },
36
+ { code: "it", language: "it-IT", name: "Italiano" },
37
+ // Bring your own language — Mapo strings fall back to defaultLocale
38
+ { code: "fr", language: "fr-FR", name: "Français", file: "fr.json" },
39
+ ],
40
+ },
41
+ });
42
+ ```
43
+
44
+ ## Overriding / extending translations
45
+
46
+ Put your messages in the app's `i18n/locales/` directory. Project-level messages are merged **on top** of the Mapo catalogs, so re-declaring a `mapo.*` key overrides it:
47
+
48
+ ```json
49
+ // i18n/locales/en.json
50
+ {
51
+ "mapo": { "listHead": { "addNew": "New entry" } },
52
+ "myApp": { "customTitle": "My dashboard" }
53
+ }
54
+ ```
55
+
56
+ ## Typed keys
57
+
58
+ ```ts
59
+ import type { MapoI18nKey, MapoMessages } from "@mapomodule/i18n/types";
60
+ ```
61
+
62
+ Full documentation: [`docs/modules/i18n.md`](../../../docs/modules/i18n.md).
@@ -0,0 +1,30 @@
1
+ import en from '../dist/runtime/locales/mapo.en.json';
2
+ export { MapoI18nOptions, MapoLocale } from './module.mjs';
3
+ import '@nuxt/schema';
4
+
5
+ /**
6
+ * Shape of the Mapo built-in message catalog (English is the source of
7
+ * truth — every locale ships the same keys).
8
+ */
9
+ type MapoMessages = typeof en;
10
+ /**
11
+ * Recursively builds the union of dot-separated key paths of an object type.
12
+ * `{ mapo: { save: string } }` → `"mapo" | "mapo.save"`.
13
+ */
14
+ type DotPaths<T, Prefix extends string = ""> = {
15
+ [K in keyof T & string]: T[K] extends Record<string, unknown> ? `${Prefix}${K}` | DotPaths<T[K], `${Prefix}${K}.`> : `${Prefix}${K}`;
16
+ }[keyof T & string];
17
+ /**
18
+ * Union of every valid Mapo translation key
19
+ * (e.g. `"mapo.save"`, `"mapo.menuManager.noSelectedNode"`).
20
+ *
21
+ * Useful to type helper wrappers in consuming apps:
22
+ * ```ts
23
+ * import type { MapoI18nKey } from "@mapomodule/i18n/types";
24
+ * const key: MapoI18nKey = "mapo.save";
25
+ * t(key);
26
+ * ```
27
+ */
28
+ type MapoI18nKey = DotPaths<MapoMessages>;
29
+
30
+ export type { MapoI18nKey, MapoMessages };
@@ -0,0 +1,27 @@
1
+ import en from "./runtime/locales/mapo.en.json";
2
+ export type { MapoI18nOptions, MapoLocale } from "./module";
3
+ /**
4
+ * Shape of the Mapo built-in message catalog (English is the source of
5
+ * truth — every locale ships the same keys).
6
+ */
7
+ export type MapoMessages = typeof en;
8
+ /**
9
+ * Recursively builds the union of dot-separated key paths of an object type.
10
+ * `{ mapo: { save: string } }` → `"mapo" | "mapo.save"`.
11
+ */
12
+ type DotPaths<T, Prefix extends string = ""> = {
13
+ [K in keyof T & string]: T[K] extends Record<string, unknown> ? `${Prefix}${K}` | DotPaths<T[K], `${Prefix}${K}.`> : `${Prefix}${K}`;
14
+ }[keyof T & string];
15
+ /**
16
+ * Union of every valid Mapo translation key
17
+ * (e.g. `"mapo.save"`, `"mapo.menuManager.noSelectedNode"`).
18
+ *
19
+ * Useful to type helper wrappers in consuming apps:
20
+ * ```ts
21
+ * import type { MapoI18nKey } from "@mapomodule/i18n/types";
22
+ * const key: MapoI18nKey = "mapo.save";
23
+ * t(key);
24
+ * ```
25
+ */
26
+ export type MapoI18nKey = DotPaths<MapoMessages>;
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAEhD,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE5D;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,EAAE,CAAC;AAErC;;;GAGG;AACH,KAAK,QAAQ,CAAC,CAAC,EAAE,MAAM,SAAS,MAAM,GAAG,EAAE,IAAI;KAC5C,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACzD,GAAG,MAAM,GAAG,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,GAClD,GAAG,MAAM,GAAG,CAAC,EAAE;CACpB,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;AAEpB;;;;;;;;;;GAUG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC"}
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,70 @@
1
+ import { NuxtModule } from '@nuxt/schema';
2
+
3
+ /**
4
+ * Locale descriptor accepted by `mapoI18n.locales`.
5
+ * Mirrors the shape of `@nuxtjs/i18n` LocaleObject without importing its types
6
+ * (they are only available once the module is installed in the app).
7
+ */
8
+ interface MapoLocale {
9
+ /** Locale code used in URLs/cookies and by `setLocale` (e.g. `"en"`). */
10
+ code: string;
11
+ /** BCP-47 language tag used for SEO/browser matching (e.g. `"en-US"`). */
12
+ language?: string;
13
+ /** Human readable name shown by `<MapoLangSwitcher>`. */
14
+ name?: string;
15
+ /**
16
+ * Translation file(s) resolved from the app's `i18n/locales/` directory.
17
+ * Only needed when the app provides its own messages for this locale.
18
+ */
19
+ file?: string;
20
+ /** Multiple translation files merged in order. */
21
+ files?: string[];
22
+ /** Text direction. */
23
+ dir?: "ltr" | "rtl" | "auto";
24
+ [key: string]: unknown;
25
+ }
26
+ interface MapoI18nOptions {
27
+ /**
28
+ * Default UI locale. Also used as `fallbackLocale` for missing keys.
29
+ * @default "en"
30
+ */
31
+ defaultLocale?: string;
32
+ /**
33
+ * Locales available in the app. Defaults to English + Italian (the two
34
+ * languages Mapo ships translations for). Add entries with `file`/`files`
35
+ * to bring your own languages — Mapo strings fall back to `defaultLocale`
36
+ * for locales it doesn't cover.
37
+ */
38
+ locales?: MapoLocale[];
39
+ /**
40
+ * Detect the browser language on first visit and persist the choice in a
41
+ * cookie. Set `false` to always start from `defaultLocale`.
42
+ * @default true
43
+ */
44
+ detectBrowserLanguage?: boolean;
45
+ /**
46
+ * Extra options forwarded verbatim to `@nuxtjs/i18n` (they win over the
47
+ * Mapo defaults). Use this as an escape hatch for advanced setups —
48
+ * e.g. `strategy`, `customRoutes`, `vueI18n` config path…
49
+ * @see https://i18n.nuxtjs.org/docs/api/options
50
+ */
51
+ i18n?: Record<string, unknown>;
52
+ }
53
+ /**
54
+ * Nuxt module that wires `@nuxtjs/i18n` into a Mapo app:
55
+ *
56
+ * - registers Mapo's built-in UI translations (`en`, `it`) under the `mapo.*`
57
+ * key namespace via the `i18n:registerModule` hook;
58
+ * - installs `@nuxtjs/i18n` with admin-friendly defaults (`no_prefix`
59
+ * strategy, browser detection, cookie persistence) unless the app already
60
+ * declares it in `modules[]` — in that case the app's configuration wins
61
+ * and this module only contributes the Mapo message catalogs.
62
+ *
63
+ * Apps override single strings by shipping the same key in their own locale
64
+ * files (`i18n/locales/<code>.json`): project-level messages are merged on
65
+ * top of module-registered ones.
66
+ */
67
+ declare const _default: NuxtModule<MapoI18nOptions, MapoI18nOptions, false>;
68
+
69
+ export { _default as default };
70
+ export type { MapoI18nOptions, MapoLocale };
@@ -0,0 +1,68 @@
1
+ import type { NuxtModule } from "@nuxt/schema";
2
+ /**
3
+ * Locale descriptor accepted by `mapoI18n.locales`.
4
+ * Mirrors the shape of `@nuxtjs/i18n` LocaleObject without importing its types
5
+ * (they are only available once the module is installed in the app).
6
+ */
7
+ export interface MapoLocale {
8
+ /** Locale code used in URLs/cookies and by `setLocale` (e.g. `"en"`). */
9
+ code: string;
10
+ /** BCP-47 language tag used for SEO/browser matching (e.g. `"en-US"`). */
11
+ language?: string;
12
+ /** Human readable name shown by `<MapoLangSwitcher>`. */
13
+ name?: string;
14
+ /**
15
+ * Translation file(s) resolved from the app's `i18n/locales/` directory.
16
+ * Only needed when the app provides its own messages for this locale.
17
+ */
18
+ file?: string;
19
+ /** Multiple translation files merged in order. */
20
+ files?: string[];
21
+ /** Text direction. */
22
+ dir?: "ltr" | "rtl" | "auto";
23
+ [key: string]: unknown;
24
+ }
25
+ export interface MapoI18nOptions {
26
+ /**
27
+ * Default UI locale. Also used as `fallbackLocale` for missing keys.
28
+ * @default "en"
29
+ */
30
+ defaultLocale?: string;
31
+ /**
32
+ * Locales available in the app. Defaults to English + Italian (the two
33
+ * languages Mapo ships translations for). Add entries with `file`/`files`
34
+ * to bring your own languages — Mapo strings fall back to `defaultLocale`
35
+ * for locales it doesn't cover.
36
+ */
37
+ locales?: MapoLocale[];
38
+ /**
39
+ * Detect the browser language on first visit and persist the choice in a
40
+ * cookie. Set `false` to always start from `defaultLocale`.
41
+ * @default true
42
+ */
43
+ detectBrowserLanguage?: boolean;
44
+ /**
45
+ * Extra options forwarded verbatim to `@nuxtjs/i18n` (they win over the
46
+ * Mapo defaults). Use this as an escape hatch for advanced setups —
47
+ * e.g. `strategy`, `customRoutes`, `vueI18n` config path…
48
+ * @see https://i18n.nuxtjs.org/docs/api/options
49
+ */
50
+ i18n?: Record<string, unknown>;
51
+ }
52
+ /**
53
+ * Nuxt module that wires `@nuxtjs/i18n` into a Mapo app:
54
+ *
55
+ * - registers Mapo's built-in UI translations (`en`, `it`) under the `mapo.*`
56
+ * key namespace via the `i18n:registerModule` hook;
57
+ * - installs `@nuxtjs/i18n` with admin-friendly defaults (`no_prefix`
58
+ * strategy, browser detection, cookie persistence) unless the app already
59
+ * declares it in `modules[]` — in that case the app's configuration wins
60
+ * and this module only contributes the Mapo message catalogs.
61
+ *
62
+ * Apps override single strings by shipping the same key in their own locale
63
+ * files (`i18n/locales/<code>.json`): project-level messages are merged on
64
+ * top of module-registered ones.
65
+ */
66
+ declare const _default: NuxtModule<MapoI18nOptions, MapoI18nOptions, false>;
67
+ export default _default;
68
+ //# sourceMappingURL=module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAK/C;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,sBAAsB;IACtB,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IAEvB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAOD;;;;;;;;;;;;;GAaG;;AACH,wBAyGyC"}
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "@mapomodule/i18n",
3
+ "configKey": "mapoI18n",
4
+ "version": "2.0.0-beta.2",
5
+ "builder": {
6
+ "@nuxt/module-builder": "1.0.2",
7
+ "unbuild": "unknown"
8
+ }
9
+ }
@@ -0,0 +1,70 @@
1
+ import { defineNuxtModule, createResolver, addImports, hasNuxtModule, addTemplate, installModule } from '@nuxt/kit';
2
+ import { defu } from 'defu';
3
+
4
+ const MAPO_LOCALES = [
5
+ { code: "en", language: "en-US", name: "English" },
6
+ { code: "it", language: "it-IT", name: "Italiano" }
7
+ ];
8
+ const module$1 = defineNuxtModule({
9
+ meta: {
10
+ name: "@mapomodule/i18n",
11
+ configKey: "mapoI18n"
12
+ },
13
+ defaults: {
14
+ defaultLocale: "en",
15
+ detectBrowserLanguage: true
16
+ },
17
+ async setup(options, nuxt) {
18
+ const resolver = createResolver(import.meta.url);
19
+ addImports([
20
+ {
21
+ name: "useMapoT",
22
+ from: resolver.resolve("./runtime/composables/useMapoT")
23
+ }
24
+ ]);
25
+ nuxt.hook("i18n:registerModule", (register) => {
26
+ register({
27
+ langDir: resolver.resolve("./runtime/locales"),
28
+ locales: [
29
+ { code: "en", language: "en-US", file: "mapo.en.json" },
30
+ { code: "it", language: "it-IT", file: "mapo.it.json" }
31
+ ]
32
+ });
33
+ });
34
+ if (hasNuxtModule("@nuxtjs/i18n")) {
35
+ return;
36
+ }
37
+ const vueI18nConfig = addTemplate({
38
+ filename: "mapo-i18n.config.mjs",
39
+ write: true,
40
+ getContents: () => `export default () => ({
41
+ legacy: false,
42
+ fallbackLocale: ${JSON.stringify(options.defaultLocale ?? "en")},
43
+ });
44
+ `
45
+ });
46
+ const i18nConfig = defu(options.i18n ?? {}, {
47
+ strategy: "no_prefix",
48
+ defaultLocale: options.defaultLocale ?? "en",
49
+ locales: options.locales ?? MAPO_LOCALES,
50
+ detectBrowserLanguage: options.detectBrowserLanguage ? {
51
+ useCookie: true,
52
+ cookieKey: "i18n_redirected",
53
+ redirectOn: "root"
54
+ } : false,
55
+ vueI18n: vueI18nConfig.dst
56
+ });
57
+ const nuxtOptions = nuxt.options;
58
+ nuxtOptions.i18n = defu(nuxtOptions.i18n ?? {}, i18nConfig);
59
+ const rootLayer = nuxtOptions._layers?.[0];
60
+ if (rootLayer) {
61
+ rootLayer.config.i18n = defu(
62
+ rootLayer.config.i18n ?? {},
63
+ i18nConfig
64
+ );
65
+ }
66
+ await installModule("@nuxtjs/i18n");
67
+ }
68
+ });
69
+
70
+ export { module$1 as default };
@@ -0,0 +1,12 @@
1
+ type TranslateFn = (key: string, named?: Record<string, unknown>) => string;
2
+ /**
3
+ * Returns the global vue-i18n `t` function bound to the app's i18n instance.
4
+ *
5
+ * Use this in contexts where `useI18n()` is not available — Pinia store
6
+ * actions, composables invoked outside component `setup`, imperative
7
+ * snack/confirm messages. Inside components prefer `useI18n()` from
8
+ * `vue-i18n`, which is reactive to locale changes in render functions.
9
+ */
10
+ export declare function useMapoT(): TranslateFn;
11
+ export {};
12
+ //# sourceMappingURL=useMapoT.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMapoT.d.ts","sourceRoot":"","sources":["../../../src/runtime/composables/useMapoT.ts"],"names":[],"mappings":"AAEA,KAAK,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;AAE5E;;;;;;;GAOG;AACH,wBAAgB,QAAQ,IAAI,WAAW,CAQtC"}
@@ -0,0 +1,6 @@
1
+ import { useNuxtApp } from "nuxt/app";
2
+ export function useMapoT() {
3
+ const { $i18n } = useNuxtApp();
4
+ if (!$i18n?.t) return (key) => key;
5
+ return (key, named) => named ? $i18n.t(key, named) : $i18n.t(key);
6
+ }
@@ -0,0 +1,261 @@
1
+ {
2
+ "mapo": {
3
+ "cancel": "Cancel",
4
+ "save": "Save",
5
+ "apply": "Apply",
6
+ "confirm": "Confirm",
7
+ "ok": "OK",
8
+ "close": "Close",
9
+ "edit": "Edit",
10
+ "delete": "Delete",
11
+ "add": "Add",
12
+ "remove": "Remove",
13
+ "clear": "Clear",
14
+ "expand": "Expand",
15
+ "collapse": "Collapse",
16
+ "search": "Search...",
17
+ "create": "Create",
18
+ "new": "New",
19
+ "createContinue": "Create and continue",
20
+ "saveContinue": "Save and continue",
21
+ "back": "Back",
22
+ "leave": "Leave",
23
+ "preview": "Preview",
24
+ "refresh": "Refresh",
25
+ "select": "Select",
26
+ "change": "Change",
27
+ "duplicate": "Duplicate",
28
+ "restore": "Restore",
29
+ "discard": "Discard",
30
+ "loading": "Loading...",
31
+ "genericError": "Something went wrong, please try again later...",
32
+ "saveSuccess": "Saved successfully",
33
+ "createSuccess": "Created successfully",
34
+ "deleteSuccess": "Deleted successfully",
35
+ "saveError": "Failed to save",
36
+ "deleteError": "Failed to delete",
37
+ "loadError": "Failed to load data",
38
+ "loadItemError": "Failed to load item",
39
+ "fixErrors": "Please fix the errors before saving.",
40
+ "confirmDelete": "Are you sure you want to delete this item?",
41
+ "unsavedData": "Unsaved changes",
42
+ "confirmLeaveChanges": "You have unsaved changes. Do you want to leave without saving?",
43
+ "fetchingData": "Fetching data...",
44
+ "login": {
45
+ "welcome": "Welcome to Mapo",
46
+ "subtitle": "Enter your credentials to continue",
47
+ "tagline": "A modern admin framework built on Nuxt 4, Pinia, and Nuxt UI v4.",
48
+ "invalidCredentials": "Invalid credentials. Please try again."
49
+ },
50
+ "logout": "Logout",
51
+ "signIn": "Sign in",
52
+ "username": "Username",
53
+ "password": "Password",
54
+ "name": "Name",
55
+ "title": "Title",
56
+ "description": "Description",
57
+ "mime": "MIME Type",
58
+ "fileName": "File name",
59
+ "file": "File",
60
+ "folder": "Folder",
61
+ "created": "Created at",
62
+ "size": "Size",
63
+ "altTag": "Alt text",
64
+ "url": "URL",
65
+ "linkedModels": "Linked models",
66
+ "latitude": "Latitude",
67
+ "longitude": "Longitude",
68
+ "language": "Language",
69
+ "index": {
70
+ "welcomeMessage": "Congratulations!! 🥳 You successfully installed Mapo!"
71
+ },
72
+ "themeToggle": {
73
+ "light": "Switch to light mode",
74
+ "dark": "Switch to dark mode"
75
+ },
76
+ "confirmDialog": {
77
+ "areYouSure": "Are you sure of what you are doing?"
78
+ },
79
+ "dropArea": {
80
+ "dropOrClick": "Drop your file(s) here, or click to select them.",
81
+ "dropHere": "Drop here",
82
+ "onlyOneFile": "Only one file can be uploaded at a time..."
83
+ },
84
+ "detail": {
85
+ "deleteQuestion": "Are you sure you want to delete this item? This action cannot be undone.",
86
+ "draftFound": "You have a local draft that was not saved. Do you want to restore it or discard it?",
87
+ "draftSavedAt": "Unsaved draft found — last edited {date}"
88
+ },
89
+ "form": {
90
+ "required": "This field is required.",
91
+ "tabErrors": "This tab contains errors"
92
+ },
93
+ "fksField": {
94
+ "searchSelect": "Search and select...",
95
+ "noResults": "No results found",
96
+ "noItems": "No items available"
97
+ },
98
+ "dateField": {
99
+ "selectDate": "Select date",
100
+ "selectDateTime": "Select date and time"
101
+ },
102
+ "fileField": {
103
+ "removeFile": "Remove file"
104
+ },
105
+ "mediaField": {
106
+ "selectMedia": "Select media"
107
+ },
108
+ "mediaM2MField": {
109
+ "addMedia": "Add media"
110
+ },
111
+ "enhancedMediaField": {
112
+ "altText": "Alt text",
113
+ "caption": "Caption"
114
+ },
115
+ "repeater": {
116
+ "repeater": "Repeater",
117
+ "nItems": "{n} item | {n} items",
118
+ "nSelected": "{n} selected",
119
+ "all": "All",
120
+ "collapseAll": "Collapse all",
121
+ "expandAll": "Expand all",
122
+ "deleteItem": "Delete item",
123
+ "deleteItems": "Delete items",
124
+ "confirmBulkDelete": "Delete {count} selected items?",
125
+ "actionBlocked": "Action blocked",
126
+ "minItemsBlock": "Cannot delete: at least {min} items must remain.",
127
+ "undoLastAction": "Undo last action",
128
+ "bulkSelection": "Bulk selection",
129
+ "exitSelection": "Exit selection",
130
+ "duplicateSelected": "Duplicate selected",
131
+ "duplicateLimited": "Only {slots} of {count} can be duplicated (maxItems reached)",
132
+ "moveToTop": "Move to top",
133
+ "moveUp": "Move up",
134
+ "moveDown": "Move down",
135
+ "position": "Position",
136
+ "editFullScreen": "Edit full screen",
137
+ "empty": "No items. Click \"Add\" to start."
138
+ },
139
+ "seoPreview": {
140
+ "seoTitle": "SEO title",
141
+ "metaDescription": "Meta description",
142
+ "googlePreview": "Google preview",
143
+ "titlePlaceholder": "Page title...",
144
+ "descriptionPlaceholder": "Page description...",
145
+ "defaultTitle": "Page title",
146
+ "defaultDescription": "Page description that will appear in Google search results."
147
+ },
148
+ "wygEditor": {
149
+ "insertImage": "Insert image",
150
+ "requiresUikit": "Requires {'@'}mapomodule/uikit"
151
+ },
152
+ "listActions": {
153
+ "bulkActions": "Bulk actions...",
154
+ "permanentDelete": "Delete permanently",
155
+ "confirmBulk": "This action will be applied to all items. Do you want to continue?",
156
+ "confirmBulkCount": "This action will be applied to {count} item(s). Do you want to continue?",
157
+ "actionCompleted": "Action completed",
158
+ "actionFailed": "Action failed"
159
+ },
160
+ "listFilters": {
161
+ "filters": "Filters",
162
+ "clearAll": "Clear all"
163
+ },
164
+ "listQuickEdit": {
165
+ "newItem": "New item"
166
+ },
167
+ "listTable": {
168
+ "deleteItemTitle": "Delete item",
169
+ "itemDeleted": "Item deleted",
170
+ "deleteItemError": "Failed to delete item",
171
+ "orderSaved": "Order saved",
172
+ "orderError": "Failed to save order",
173
+ "selectAllRows": "Select all rows",
174
+ "selectRow": "Select row",
175
+ "dragToReorder": "Drag to reorder",
176
+ "clearToReorder": "Clear search & sorting to reorder",
177
+ "noItems": "No items found",
178
+ "totalItems": "{total} items",
179
+ "perPage": "{n} / page"
180
+ },
181
+ "menuManager": {
182
+ "menu": "Menu",
183
+ "noSelectedNode": "Select a node to edit or create a new one."
184
+ },
185
+ "menuTreeview": {
186
+ "newNode": "Create node",
187
+ "noRootNodes": "No nodes here. Create a new one!",
188
+ "deleteTitle": "Delete node",
189
+ "areYouSureDelete": "Are you sure you want to delete this node and all its children?",
190
+ "maxDepthReached": "Maximum nesting depth reached ({max} levels)"
191
+ },
192
+ "menuNodeEditor": {
193
+ "editNode": "Editing",
194
+ "title": "Title",
195
+ "linkTypeLabel": "Link type",
196
+ "styleLabel": "Style",
197
+ "openInNewTabLabel": "Open in a new tab",
198
+ "relContentTypeLabel": "Type of page",
199
+ "relPageIdLabel": "Page",
200
+ "staticLabel": "Static URL",
201
+ "relational": "Relational",
202
+ "static": "Static",
203
+ "nodeErrors": "This node contains errors"
204
+ },
205
+ "mediaEditor": {
206
+ "details": "Details",
207
+ "defaultLang": "Default",
208
+ "openInNewTab": "Open in new tab",
209
+ "confirmDelete": "Are you sure you want to delete \"{name}\"?"
210
+ },
211
+ "mediaFileChanger": {
212
+ "replaceFile": "Replace file",
213
+ "dragOrClick": "Drag or click to choose a file",
214
+ "keepUrl": "Keep current URL"
215
+ },
216
+ "mediaFolders": {
217
+ "folders": "Folders",
218
+ "goBack": "Back to root",
219
+ "noFolders": "No folders here... Create a new one!",
220
+ "newFolder": "New folder",
221
+ "folderName": "Folder name",
222
+ "allFolder": "All",
223
+ "imageFolder": "Images",
224
+ "videoFolder": "Videos",
225
+ "audioFolder": "Audio",
226
+ "docFolder": "Documents",
227
+ "deleteTitle": "Delete folder",
228
+ "confirmDelete": "Delete folder \"{name}\"? Media inside it will not be deleted."
229
+ },
230
+ "mediaGallery": {
231
+ "noMediaFound": "No media found",
232
+ "selectAll": "Select page",
233
+ "deselectAll": "Deselect page",
234
+ "nSelected": "{number} selected",
235
+ "deleteTitle": "Delete selected media",
236
+ "deleteSelectedLabel": "Delete selected",
237
+ "deleteSelected": "You are going to delete {number} assets. Do you want to continue?",
238
+ "deleteSuccess": "{number} assets deleted!"
239
+ },
240
+ "mediaManager": {
241
+ "root": "Media",
242
+ "gallery": "Gallery",
243
+ "uploader": "Upload",
244
+ "fileInfo": "Media updated",
245
+ "deleteTitle": "Delete media",
246
+ "selectMedia": "Select media",
247
+ "selectAMedia": "Select a media"
248
+ },
249
+ "mediaUploader": {
250
+ "dragHere": "Drag files here or",
251
+ "browse": "browse",
252
+ "limits": "Images up to {img} MB · Videos up to {vid} MB",
253
+ "nSelected": "{n} file selected | {n} files selected",
254
+ "uploadCta": "Upload {n} file | Upload {n} files",
255
+ "uploaded": "Uploaded",
256
+ "uploadFailed": "Upload failed",
257
+ "fileTooLarge": "File \"{name}\" too large (max {max} MB)",
258
+ "success": "{numberFiles} files successfully uploaded"
259
+ }
260
+ }
261
+ }