@futurra/multilinguist 0.0.0-stage → 1.7.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/README.md CHANGED
@@ -1,3 +1,234 @@
1
- # Temporary Holding Version
1
+ # Nuxt Multilinguist module
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Multilinguist is a simple but smoothly working module for easy and seamless localization implementation for Nuxt
4
+ applications.
5
+
6
+ ## Key Features
7
+
8
+ - Easy translations that you're used to
9
+ - Works perfectly fine on both SSR + CSR
10
+ - No memory leaks and running out of memory errors
11
+ - Autocompletion & validation of keys
12
+ - Autodetection of browser's locale
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @futurra/multilinguist
18
+ ```
19
+
20
+ Then, add the module to your nuxt.config
21
+
22
+ ```nuxt.config.ts
23
+ export default defineNuxtConfig({
24
+ modules: [
25
+ "@futurra/multilinguist",
26
+ ],
27
+ multilinguist: {
28
+ defaultLocale: "en", // string representing key to your default (fallback) locale
29
+ supportedLanguages: ["en", "es"], // array of strings representing all available locales' keys
30
+ },
31
+ })
32
+ ```
33
+
34
+ Then, create a "locales" directory in root directory of your project.
35
+
36
+ ![directory_structure.png](directory_structure.png)
37
+
38
+ Now, you're ready to use Multilinguist Module!
39
+
40
+ After running your project, you can see the following warning:
41
+
42
+ ![vite-warning.png](vite-warning.png)
43
+
44
+ **Dont be scared**, this is just a message from the module, indicating that your locales are typed, and that the module
45
+ can properly perform type-checks and autocompletion.
46
+
47
+ Also, on both SSR and CSR, you will see the following message:
48
+
49
+ ![initialized.png](initialized.png)
50
+
51
+ It indicated that the module has been initialized successfully.
52
+
53
+ To disable logs, you can set the `logging` option in your nuxt.config to `false` (by default, it is `true`):
54
+
55
+ ```nuxt.config.ts
56
+ export default defineNuxtConfig({
57
+ modules: [
58
+ "@futurra/multilinguist",
59
+ ],
60
+ multilinguist: {
61
+ defaultLocale: "en",
62
+ supportedLanguages: ["en", "es"],
63
+ logging: false, // Boolean value to define if the module should send internal logs to console
64
+ },
65
+ })
66
+ ```
67
+ Also, Multilinguist offers a functionality to set the default browser's locale as default if it is available in the supported languages array.
68
+
69
+ To disable this option, you can set the `setBrowserLanguage` option to `false` as it is `true` by default:
70
+
71
+ ```nuxt.config.ts
72
+ export default defineNuxtConfig({
73
+ modules: [
74
+ "@futurra/multilinguist",
75
+ ],
76
+ multilinguist: {
77
+ defaultLocale: "en",
78
+ supportedLanguages: ["en", "es"],
79
+ logging: false,
80
+ setBrowserLanguage: false, // by default: true
81
+ },
82
+ })
83
+ ```
84
+
85
+ Also, if you want to use a different folder name for your locales' files, or you want to specify other path to the directory, you can set the `localesPath` option in your nuxt.config:
86
+
87
+ ```nuxt.config.ts
88
+ export default defineNuxtConfig({
89
+ modules: [
90
+ "@futurra/multilinguist",
91
+ ],
92
+ multilinguist: {
93
+ defaultLocale: "en",
94
+ supportedLanguages: ["en", "es"],
95
+ logging: false,
96
+ setBrowserLanguage: false, // by default: true
97
+ localesPath: "./languages", // by default: "./locales"
98
+ },
99
+ })
100
+ ```
101
+
102
+ ### Important! Keep in mind, that it is not recommended to use "public" folder for your locales' files, as it may lead to rendering, security and other issues.
103
+
104
+ # Usage
105
+
106
+ ### t()—famous translate function
107
+
108
+ ```vue
109
+
110
+ <script setup lang="ts">
111
+ const { t } = useMultilinguist(); // Call useMultilinguist composable to get the translation function
112
+
113
+ const pageTitle = computed(() => {
114
+ return t("Hello, World");
115
+ });
116
+ </script>
117
+
118
+ <template>
119
+ <h3>{{ pageTitle }}</h3>
120
+ <button>{{ t("Switch Locale") }}</button>
121
+ </template>
122
+ ```
123
+
124
+ It also supports nested keys and dynamic keys with variables;
125
+ you only need to pass the second argument, an object with used in the key variables:
126
+
127
+ ```vue
128
+
129
+ <template>
130
+ <span>{{ t("Paste your variable here", { variable: locale }) }}</span>
131
+ </template>
132
+ ```
133
+
134
+ And your JSON must look like that:
135
+
136
+ ```json
137
+ {
138
+ "Paste your variable here": "Here is your variable: {variable}"
139
+ }
140
+ ```
141
+
142
+ ```vue
143
+
144
+ <script setup lang="ts">
145
+ const { t } = useMultilinguist(); // Call useMultilinguist composable to get the translation function
146
+
147
+ const pageTitle = computed(() => {
148
+ return t("Hello, World");
149
+ });
150
+ </script>
151
+
152
+ <template>
153
+ <h3>{{ pageTitle }}</h3>
154
+ <button>{{ t("Switch Locale") }}</button>
155
+ <br />
156
+ <span>{{ t("Paste your variable here", { variable: locale }) }}</span>
157
+ <br />
158
+ <h1>{{ t("nested.Nested key") }}: <span>{{ t("nested.Language") }}</span></h1>
159
+ </template>
160
+ ```
161
+
162
+ You can already see how keys auto-completion works:
163
+
164
+ ![autocompletion.png](autocompletion.png)
165
+
166
+ And validation:
167
+
168
+ ![validation.png](validation.png)
169
+
170
+ ### Set another value to the current locale:
171
+
172
+ ```vue
173
+
174
+ <script setup lang="ts">
175
+ const { t, setLocale } = useMultilinguist();
176
+ // setLocale function accepts a string that should match one of defined
177
+ // in the nuxt.config strings from supportedLanguages array
178
+
179
+ const pageTitle = computed(() => {
180
+ return t("Hello, World");
181
+ });
182
+ </script>
183
+
184
+ <template>
185
+ <h3>{{ pageTitle }}</h3>
186
+ <button @click="setLocale('es')">{{ t("Switch Locale") }}</button>
187
+ </template>
188
+ ```
189
+
190
+ ### Get current locale
191
+
192
+ ```vue
193
+
194
+ <script setup lang="ts">
195
+ const { t, setLocale, locale } = useMultilinguist();
196
+ // locale is SSR friendly, shared among the app ref state
197
+
198
+ const pageTitle = computed(() => {
199
+ return t("Hello, World");
200
+ });
201
+ </script>
202
+
203
+ <template>
204
+ <h3>{{ pageTitle }}</h3>
205
+ <h6>Current Locale: {{ locale }}</h6>
206
+ <button @click="setLocale('es')">{{ t("Switch Locale") }}</button>
207
+ </template>
208
+ ```
209
+
210
+ ### Get locales list
211
+
212
+ ```vue
213
+
214
+ <script setup lang="ts">
215
+ const { t, setLocale, locale, locales } = useMultilinguist();
216
+ // Locales is a computed ref, which value is being set from your nuxt.config
217
+
218
+ const pageTitle = computed(() => {
219
+ return t("Hello, World");
220
+ });
221
+ </script>
222
+
223
+ <template>
224
+ <h3>{{ pageTitle }}</h3>
225
+ <h6>Current Locale: {{ locale }}</h6>
226
+ <span
227
+ v-for="localeItem from locales"
228
+ :key="localeItem"
229
+ >
230
+ | {{ localeItem }} |
231
+ </span>
232
+ <button @click="setLocale('es')">{{ t("Switch Locale") }}</button>
233
+ </template>
234
+ ```
@@ -0,0 +1,5 @@
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
+
3
+ declare const _default: _nuxt_schema.NuxtModule<_nuxt_schema.ModuleOptions, _nuxt_schema.ModuleOptions, false>;
4
+
5
+ export { _default as default };
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@futurra/multilinguist",
3
+ "configKey": "multilinguist",
4
+ "version": "1.6.2",
5
+ "compatibility": {
6
+ "nuxt": "^3.0.0 || ^4.0.0"
7
+ },
8
+ "defaults": {
9
+ "logging": true,
10
+ "defaultLocale": "",
11
+ "supportedLanguages": [],
12
+ "setBrowserLanguage": true
13
+ },
14
+ "builder": {
15
+ "@nuxt/module-builder": "1.0.1",
16
+ "unbuild": "3.6.0"
17
+ }
18
+ }
@@ -0,0 +1,125 @@
1
+ import { defineNuxtModule, createResolver, addPlugin, addImportsDir } from '@nuxt/kit';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ function flattenKeys(obj, prefix = "") {
6
+ return Object.entries(obj).flatMap(([key, value]) => {
7
+ const fullKey = prefix ? `${prefix}.${key}` : key;
8
+ if (typeof value === "object" && value !== null) {
9
+ return flattenKeys(value, fullKey);
10
+ }
11
+ return [fullKey];
12
+ });
13
+ }
14
+ const generateOutputString = (func) => {
15
+ return `
16
+ // AUTO-GENERATED FILE \u2014 DO NOT EDIT MANUALLY
17
+
18
+ export interface TranslationMessages {
19
+ ${func()}
20
+ }
21
+
22
+ export type LocaleKey = keyof TranslationMessages;
23
+
24
+ export type TFunction = <K extends LocaleKey>(
25
+ key: K,
26
+ variables?: Record<string, string>
27
+ ) => string;
28
+
29
+ declare global {
30
+ type LocaleKey = keyof TranslationMessages;
31
+ type TFunction = <K extends LocaleKey>(
32
+ key: K,
33
+ variables?: Record<string, string>
34
+ ) => string;
35
+ }
36
+
37
+ declare module '#app' {
38
+ interface NuxtApp {
39
+ $t: TFunction;
40
+ t: TFunction;
41
+ }
42
+ }
43
+
44
+ declare module 'vue' {
45
+ interface ComponentCustomProperties {
46
+ $t: TFunction;
47
+ t: TFunction;
48
+ }
49
+ }
50
+ `;
51
+ };
52
+ function GenerateLocaleKeysPlugin(defaultLocaleFromConfig, absoluteLocalesPath, outPath, logging = true) {
53
+ async function generateTypes() {
54
+ const defaultLocalePath = path.join(absoluteLocalesPath, `${defaultLocaleFromConfig}.json`);
55
+ if (!fs.existsSync(defaultLocalePath)) {
56
+ console?.error(`\u274C Default locale file not found: ${defaultLocalePath}`);
57
+ return;
58
+ }
59
+ const json = JSON.parse(fs.readFileSync(defaultLocalePath, "utf-8"));
60
+ const keys = flattenKeys(json);
61
+ const output = generateOutputString(() => keys.map((key) => ` ${JSON.stringify(key)}: string;`).join("\n"));
62
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
63
+ fs.writeFileSync(outPath, output, "utf-8");
64
+ if (logging) {
65
+ console?.warn(`\u2705 Generated types to ${outPath} from ${defaultLocalePath}`);
66
+ }
67
+ }
68
+ return {
69
+ name: "vite-plugin-generate-locales-types",
70
+ async buildStart() {
71
+ await generateTypes();
72
+ },
73
+ async handleHotUpdate(ctx) {
74
+ if (ctx.file.endsWith(".json") && ctx.file.includes(absoluteLocalesPath)) {
75
+ await generateTypes();
76
+ }
77
+ }
78
+ };
79
+ }
80
+
81
+ const module = defineNuxtModule({
82
+ meta: {
83
+ name: "@futurra/multilinguist",
84
+ configKey: "multilinguist",
85
+ version: "1.6.2",
86
+ compatibility: {
87
+ nuxt: "^3.0.0 || ^4.0.0"
88
+ },
89
+ defaults: {
90
+ logging: true,
91
+ defaultLocale: "",
92
+ supportedLanguages: [],
93
+ setBrowserLanguage: true
94
+ }
95
+ },
96
+ setup(moduleOptions, nuxtApp) {
97
+ const resolver = createResolver(import.meta.url);
98
+ addPlugin(resolver.resolve("runtime/plugin"));
99
+ addImportsDir(resolver.resolve("runtime/composables"));
100
+ nuxtApp.options.runtimeConfig.public.multilinguist = {
101
+ defaultLocale: moduleOptions.defaultLocale,
102
+ supportedLanguages: moduleOptions.supportedLanguages,
103
+ logging: typeof moduleOptions.logging === "boolean" ? moduleOptions.logging : true,
104
+ setBrowserLanguage: typeof moduleOptions.setBrowserLanguage === "boolean" ? moduleOptions.setBrowserLanguage : true
105
+ };
106
+ nuxtApp.hook("vite:extendConfig", (viteConfig) => {
107
+ viteConfig.plugins = viteConfig.plugins || [];
108
+ viteConfig.plugins.push(
109
+ GenerateLocaleKeysPlugin(
110
+ moduleOptions.defaultLocale,
111
+ `${nuxtApp.options.rootDir}/public/locales`,
112
+ resolver.resolve("./runtime/types/generated-locales.d.ts"),
113
+ moduleOptions.logging
114
+ )
115
+ );
116
+ });
117
+ nuxtApp.hook("prepare:types", ({ references }) => {
118
+ references.push({
119
+ path: resolver.resolve("./runtime/types/generated-locales.d.ts")
120
+ });
121
+ });
122
+ }
123
+ });
124
+
125
+ export { module as default };
@@ -0,0 +1,12 @@
1
+ import type { Locale, TranslationMap } from "./useLocalization.js";
2
+ /**
3
+ * Resolves a browser locale code (e.g. "pt-BR", "en-US", "de") against the list of supported locales.
4
+ *
5
+ * 1. Exact match on the full code (case-insensitive): "pt-BR" -> "pt-BR"
6
+ * 2. Fallback to the base language part before the "-": "pt-BR" -> "pt"
7
+ * 3. Otherwise the default locale.
8
+ */
9
+ export declare function resolveLocale<const T extends TranslationMap>(candidate: string | undefined | null, supportedLanguages: T, defaultLocale: Locale<T>): Locale<T>;
10
+ export default function useLocale<const T extends TranslationMap>(supportedLanguages: T, defaultLocale: Locale<T>): {
11
+ locale: import("vue").ComputedRef<Locale<T>>;
12
+ };
@@ -0,0 +1,30 @@
1
+ import { computed } from "vue";
2
+ import { useRequestHeaders } from "nuxt/app";
3
+ export function resolveLocale(candidate, supportedLanguages, defaultLocale) {
4
+ const normalized = candidate?.trim().toLowerCase();
5
+ if (!normalized) {
6
+ return defaultLocale;
7
+ }
8
+ const exact = supportedLanguages.find((supported) => supported.toLowerCase() === normalized);
9
+ if (exact) {
10
+ return exact;
11
+ }
12
+ const base = normalized.split("-")[0];
13
+ const partial = supportedLanguages.find((supported) => supported.toLowerCase() === base);
14
+ return partial ?? defaultLocale;
15
+ }
16
+ export default function useLocale(supportedLanguages, defaultLocale) {
17
+ const locale = computed(() => {
18
+ if (import.meta.server) {
19
+ const headers = useRequestHeaders(["accept-language"]);
20
+ const browserLocale = headers["accept-language"]?.split(",")[0]?.split(";")[0];
21
+ return resolveLocale(browserLocale, supportedLanguages, defaultLocale);
22
+ } else if (import.meta.client) {
23
+ return resolveLocale(navigator.language, supportedLanguages, defaultLocale);
24
+ }
25
+ return defaultLocale;
26
+ });
27
+ return {
28
+ locale
29
+ };
30
+ }
@@ -0,0 +1,13 @@
1
+ import { type ComputedRef, type Ref } from "vue";
2
+ import type { LocaleKey } from "../types/generated-locales.js";
3
+ export type TranslationMap = readonly string[];
4
+ export type Locale<T extends TranslationMap> = T[number];
5
+ export type LocaleKeys<T extends TranslationMap> = T[keyof T];
6
+ export type TMultilinguistResponse<T extends TranslationMap> = {
7
+ t<K extends LocaleKey>(key: K, variables?: Record<string, string>): string;
8
+ setLocale: (locale: Locale<T>) => void;
9
+ initLocalization: () => Promise<void>;
10
+ locale: Ref<Locale<T>>;
11
+ locales: ComputedRef<T>;
12
+ };
13
+ export default function useLocalization<const T extends TranslationMap>(supportedLanguages: T, defaultLocale: Locale<T>, setBrowserLanguage?: boolean): TMultilinguistResponse<T>;
@@ -0,0 +1,76 @@
1
+ import useLocale from "../composables/useLocale.js";
2
+ import { useCookie, useState } from "nuxt/app";
3
+ import { computed, watch } from "vue";
4
+ export default function useLocalization(supportedLanguages, defaultLocale, setBrowserLanguage = true) {
5
+ const { locale: userBrowserLocale } = useLocale(supportedLanguages, defaultLocale);
6
+ const userSelectedLocale = useCookie("multilinguist-locale", {
7
+ default: () => supportedLanguages.includes(userBrowserLocale.value) && setBrowserLanguage ? userBrowserLocale.value : defaultLocale
8
+ });
9
+ const localeFiles = import.meta.glob("@@/public/locales/*.json", { eager: true });
10
+ const loadedLanguages = useState("loaded-languages", () => ({}));
11
+ const loadLocaleMessages = async (locale2) => {
12
+ if (!loadedLanguages.value[locale2]) {
13
+ const fileKeyVersion4 = `../public/locales/${locale2}.json`;
14
+ const fileKeyVersion3 = `/public/locales/${locale2}.json`;
15
+ const messages = localeFiles[fileKeyVersion4] || localeFiles[fileKeyVersion3];
16
+ if (messages) {
17
+ loadedLanguages.value[locale2] = messages?.default;
18
+ } else {
19
+ if (!localeFiles[fileKeyVersion4]) {
20
+ throw new Error(`Locale file ${localeFiles[fileKeyVersion4]} not found`);
21
+ } else {
22
+ throw new Error(`Locale file ${localeFiles[fileKeyVersion3]} not found`);
23
+ }
24
+ }
25
+ }
26
+ };
27
+ const userPrefferableLocale = computed(() => {
28
+ return userSelectedLocale.value ? userSelectedLocale.value : userBrowserLocale.value;
29
+ });
30
+ const locale = useState("current-locale-multilinguist", () => {
31
+ return userPrefferableLocale.value || defaultLocale;
32
+ });
33
+ const t = (key, variables) => {
34
+ const messages = loadedLanguages.value[locale.value];
35
+ let translatedText = messages?.[key] ?? key;
36
+ if (key.includes(".") && !messages?.[key]) {
37
+ const nestedKeyArray = key.split(".");
38
+ translatedText = nestedKeyArray.reduce((acc, key2) => acc?.[key2], messages);
39
+ }
40
+ if (variables && typeof translatedText === "string") {
41
+ translatedText = translatedText.replace(/\{([^}]+)\}/g, (_, varKey) => {
42
+ return variables[varKey] ?? `{${varKey}}`;
43
+ });
44
+ }
45
+ return String(translatedText);
46
+ };
47
+ const setLocale = async (newLocale) => {
48
+ if (!loadedLanguages.value[newLocale] && supportedLanguages.includes(newLocale)) {
49
+ await loadLocaleMessages(newLocale);
50
+ }
51
+ userSelectedLocale.value = newLocale;
52
+ locale.value = newLocale;
53
+ };
54
+ const initLocalization = async () => {
55
+ await loadLocaleMessages(defaultLocale);
56
+ await setLocale(userPrefferableLocale.value);
57
+ };
58
+ const locales = computed(() => {
59
+ return supportedLanguages;
60
+ });
61
+ watch(
62
+ () => locale.value,
63
+ async (val) => {
64
+ if (val !== userSelectedLocale.value) {
65
+ userSelectedLocale.value = val;
66
+ }
67
+ }
68
+ );
69
+ return {
70
+ t,
71
+ setLocale,
72
+ initLocalization,
73
+ locale,
74
+ locales
75
+ };
76
+ }
@@ -0,0 +1,8 @@
1
+ import type { TranslationMap } from "./useLocalization.js";
2
+ export default function useMultilinguist(): {
3
+ t<K extends import("../types/generated-locales.js").LocaleKey>(key: K, variables?: Record<string, string>): string;
4
+ setLocale: (locale: string) => void;
5
+ initLocalization: () => Promise<void>;
6
+ locale: import("vue").Ref<string, string>;
7
+ locales: import("vue").ComputedRef<TranslationMap>;
8
+ };
@@ -0,0 +1,9 @@
1
+ import { useNuxtApp } from "nuxt/app";
2
+ export default function useMultilinguist() {
3
+ const nuxtApp = useNuxtApp();
4
+ const localization = nuxtApp.$localization || nuxtApp._localization;
5
+ if (!localization) {
6
+ throw new Error("Localization plugin not initialized");
7
+ }
8
+ return { ...localization };
9
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
+ export default _default;
@@ -0,0 +1,25 @@
1
+ import { defineNuxtPlugin } from "#app";
2
+ import useLocalization from "../runtime/composables/useLocalization";
3
+ export default defineNuxtPlugin(async (nuxtApp) => {
4
+ const config = nuxtApp.$config.public.multilinguist || {
5
+ defaultLocale: "en",
6
+ supportedLanguages: ["en"],
7
+ logging: true,
8
+ setBrowserLanguage: true
9
+ };
10
+ const supportedLanguages = config.supportedLanguages;
11
+ const defaultLocale = config.defaultLocale;
12
+ const shouldSetBrowserLanguage = config.setBrowserLanguage;
13
+ const { initLocalization, ...localizationProperties } = useLocalization(
14
+ supportedLanguages,
15
+ defaultLocale,
16
+ shouldSetBrowserLanguage
17
+ );
18
+ await initLocalization();
19
+ if (nuxtApp.$config.public.multilinguist.logging) {
20
+ console.log("[multilinguist] is initialised");
21
+ }
22
+ nuxtApp.provide("localization", localizationProperties);
23
+ nuxtApp.provide("t", localizationProperties.t);
24
+ nuxtApp._localization = localizationProperties;
25
+ });
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "../../../.nuxt/tsconfig.server.json",
3
+ }
@@ -0,0 +1,40 @@
1
+
2
+ // AUTO-GENERATED FILE — DO NOT EDIT MANUALLY
3
+
4
+ export interface TranslationMessages {
5
+ "Hello, World": string;
6
+ "Switch Locale": string;
7
+ "Paste your variable here": string;
8
+ "nested.Nested key": string;
9
+ "nested.Language": string;
10
+ "nested.nested second level.nested second level language": string;
11
+ }
12
+
13
+ export type LocaleKey = keyof TranslationMessages;
14
+
15
+ export type TFunction = <K extends LocaleKey>(
16
+ key: K,
17
+ variables?: Record<string, string>
18
+ ) => string;
19
+
20
+ declare global {
21
+ type LocaleKey = keyof TranslationMessages;
22
+ type TFunction = <K extends LocaleKey>(
23
+ key: K,
24
+ variables?: Record<string, string>
25
+ ) => string;
26
+ }
27
+
28
+ declare module '#app' {
29
+ interface NuxtApp {
30
+ $t: TFunction;
31
+ t: TFunction;
32
+ }
33
+ }
34
+
35
+ declare module 'vue' {
36
+ interface ComponentCustomProperties {
37
+ $t: TFunction;
38
+ t: TFunction;
39
+ }
40
+ }
@@ -0,0 +1,30 @@
1
+ export declare const localeFiles: {
2
+ "/locales/en.json": {
3
+ default: {
4
+ "Hello, World": string;
5
+ "Switch Locale": string;
6
+ "Paste your variable here": string;
7
+ nested: {
8
+ "Nested key": string;
9
+ Language: string;
10
+ "nested second level": {
11
+ "nested second level language": string;
12
+ };
13
+ };
14
+ };
15
+ };
16
+ "/locales/es.json": {
17
+ default: {
18
+ "Hello, World": string;
19
+ "Switch Locale": string;
20
+ "Paste your variable here": string;
21
+ nested: {
22
+ "Nested key": string;
23
+ Language: string;
24
+ "nested second level": {
25
+ "nested second level language": string;
26
+ };
27
+ };
28
+ };
29
+ };
30
+ };
@@ -0,0 +1,6 @@
1
+ import locale_0 from "../../../playground/locales/en.json";
2
+ import locale_1 from "../../../playground/locales/es.json";
3
+ export const localeFiles = {
4
+ "/locales/en.json": { default: locale_0 },
5
+ "/locales/es.json": { default: locale_1 }
6
+ };
@@ -0,0 +1,7 @@
1
+ import type { NuxtModule } from '@nuxt/schema'
2
+
3
+ import type { default as Module } from './module.mjs'
4
+
5
+ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
6
+
7
+ export { default } from './module.mjs'
package/package.json CHANGED
@@ -1,6 +1,79 @@
1
1
  {
2
2
  "name": "@futurra/multilinguist",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.7.0",
4
+ "description": "Nuxt Multilinguist module for localizations",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://gitlab.fx2.io/ai/frontend/multilinguist.git"
8
+ },
9
+ "license": "MIT",
10
+ "type": "module",
11
+ "main": "./dist/module.mjs",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/module.mjs",
15
+ "types": "./dist/types.d.mts"
16
+ }
17
+ },
18
+ "types": "./dist/types.d.mts",
19
+ "files": [
20
+ "dist",
21
+ "runtime/types"
22
+ ],
23
+ "keywords": [
24
+ "localization",
25
+ "nuxt localization",
26
+ "nuxt",
27
+ "internationalization",
28
+ "languages",
29
+ "locales",
30
+ "translation",
31
+ "localization nuxt",
32
+ "translation nuxt",
33
+ "nuxt translation",
34
+ "nuxt multilinguist",
35
+ "multilinguist nuxt",
36
+ "ssr localization"
37
+ ],
38
+ "bugs": {
39
+ "email": "michaelkukh.dev@gmail.com"
40
+ },
41
+ "scripts": {
42
+ "prepack": "nuxt-module-build build",
43
+ "dev": "nuxi dev playground",
44
+ "dev:build": "nuxi build playground",
45
+ "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
46
+ "release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
47
+ "lint": "eslint .",
48
+ "test": "vitest run",
49
+ "test:watch": "vitest watch",
50
+ "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
51
+ "build": "vite build"
52
+ },
53
+ "peerDependencies": {
54
+ "nuxt": "^3.0.0 || ^4.0.0"
55
+ },
56
+ "dependencies": {
57
+ "eslint-config-prettier": "^10.1.5",
58
+ "eslint-plugin-prettier": "^5.4.1",
59
+ "prettier": "^3.5.3"
60
+ },
61
+ "devDependencies": {
62
+ "@nuxt/devtools": "^2.4.1",
63
+ "@nuxt/eslint-config": "^1.4.1",
64
+ "@nuxt/kit": "^4.0.1",
65
+ "@nuxt/module-builder": "^1.0.1",
66
+ "@nuxt/schema": "^4.0.1",
67
+ "@nuxt/test-utils": "^3.19.1",
68
+ "@types/node": "latest",
69
+ "changelogen": "^0.6.1",
70
+ "eslint": "^9.27.0",
71
+ "nuxt": "^4.0.3",
72
+ "typescript": "~5.8.3",
73
+ "vitest": "^3.1.4",
74
+ "vue-tsc": "^2.2.10"
75
+ },
76
+ "publishConfig": {
77
+ "access": "public"
78
+ }
79
+ }