@yiiamee/multilinguist 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/README.md +18 -0
- package/dist/module.d.mts +5 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +86 -0
- package/dist/runtime/composables/useLocale.d.ts +4 -0
- package/dist/runtime/composables/useLocale.js +16 -0
- package/dist/runtime/composables/useLocalization.d.ts +11 -0
- package/dist/runtime/composables/useLocalization.js +50 -0
- package/dist/runtime/composables/useMultilinguist.d.ts +6 -0
- package/dist/runtime/composables/useMultilinguist.js +8 -0
- package/dist/runtime/plugin.d.ts +2 -0
- package/dist/runtime/plugin.js +15 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/types/generated-locales.d.ts +7 -0
- package/dist/types.d.mts +7 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Nuxt MultiLinguist module
|
|
2
|
+
|
|
3
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
4
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
+
[![License][license-src]][license-href]
|
|
6
|
+
[![Nuxt][nuxt-src]][nuxt-href]
|
|
7
|
+
|
|
8
|
+
This module is a simple, but smoothly working module for easy and seamless localization implementation in Nuxt 3.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
## Quick Setup
|
|
13
|
+
|
|
14
|
+
Install the module to your Nuxt application with one command:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx nuxi module add @nuxtjs/multilinguist
|
|
18
|
+
```
|
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { defineNuxtModule, createResolver, addPlugin, addImportsDir, addTypeTemplate } from '@nuxt/kit';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
function GenerateLocaleKeysPlugin(defaultLocaleFromConfig, localesPath, outPath) {
|
|
6
|
+
async function generateTypes() {
|
|
7
|
+
const defaultLocalePath = path.join(localesPath, `${defaultLocaleFromConfig}.json`);
|
|
8
|
+
if (!fs.existsSync(defaultLocalePath)) {
|
|
9
|
+
console?.error(`Default locale file not found: ${defaultLocalePath}`);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const json = JSON.parse(fs.readFileSync(defaultLocalePath, "utf-8"));
|
|
13
|
+
const keys = Object.keys(json);
|
|
14
|
+
const output = [
|
|
15
|
+
`// AUTO-GENERATED FILE \u2014 DO NOT EDIT MANUALLY`,
|
|
16
|
+
`export interface TranslationMessages {`,
|
|
17
|
+
...keys.map((key) => ` ${JSON.stringify(key)}: string;`),
|
|
18
|
+
`}`,
|
|
19
|
+
``,
|
|
20
|
+
`export type LocaleKey = keyof TranslationMessages;`
|
|
21
|
+
].join("\n");
|
|
22
|
+
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
23
|
+
fs.writeFileSync(outPath, output, "utf-8");
|
|
24
|
+
console?.warn(`Generated types/generated-locales.d.ts from ${defaultLocalePath}`);
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
name: "vite-plugin-generate-locales-types",
|
|
28
|
+
async buildStart() {
|
|
29
|
+
await generateTypes();
|
|
30
|
+
},
|
|
31
|
+
async handleHotUpdate(ctx) {
|
|
32
|
+
if (ctx.file.endsWith(".json") && ctx.file.includes(localesPath)) {
|
|
33
|
+
await generateTypes();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const module = defineNuxtModule({
|
|
40
|
+
meta: {
|
|
41
|
+
name: "multilinguist",
|
|
42
|
+
configKey: "multilinguist",
|
|
43
|
+
version: "0.0.1"
|
|
44
|
+
},
|
|
45
|
+
setup(moduleOptions, nuxtApp) {
|
|
46
|
+
const resolver = createResolver(import.meta.url);
|
|
47
|
+
addPlugin(resolver.resolve("./runtime/plugin"));
|
|
48
|
+
addImportsDir(resolver.resolve("runtime/composables"));
|
|
49
|
+
addTypeTemplate({
|
|
50
|
+
filename: "types/multilinguist.d.ts",
|
|
51
|
+
getContents: () => `
|
|
52
|
+
import type { TranslationMessages } from './generated-locales'
|
|
53
|
+
|
|
54
|
+
declare module '#app' {
|
|
55
|
+
interface NuxtApp {
|
|
56
|
+
$t: (key: keyof TranslationMessages) => string
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
declare module 'vue' {
|
|
61
|
+
interface ComponentCustomProperties {
|
|
62
|
+
$t: (key: keyof TranslationMessages) => string
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
`
|
|
66
|
+
});
|
|
67
|
+
nuxtApp.hook("vite:extendConfig", (viteConfig) => {
|
|
68
|
+
viteConfig.plugins = viteConfig.plugins || [];
|
|
69
|
+
viteConfig.plugins.push(GenerateLocaleKeysPlugin(moduleOptions.defaultLocale, `${nuxtApp.options.rootDir}/public/locales`, resolver.resolve("./runtime/types/generated-locales.d.ts")));
|
|
70
|
+
});
|
|
71
|
+
nuxtApp.hook("prepare:types", ({ references }) => {
|
|
72
|
+
references.push({
|
|
73
|
+
path: resolver.resolve("./runtime/types/generated-locales.d.ts")
|
|
74
|
+
});
|
|
75
|
+
references.push({
|
|
76
|
+
path: resolver.resolve("./runtime/types/multilinguist.d.ts")
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
nuxtApp.options.runtimeConfig.public.multilinguist = {
|
|
80
|
+
defaultLocale: moduleOptions.defaultLocale,
|
|
81
|
+
supportedLanguages: moduleOptions.supportedLanguages
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
export { module as default };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default function useLocale(supportedLanguages, defaultLocale) {
|
|
2
|
+
const locale = computed(() => {
|
|
3
|
+
if (import.meta.server) {
|
|
4
|
+
const headers = useRequestHeaders(["accept-language"]);
|
|
5
|
+
const locale2 = headers["accept-language"]?.split(",")[0]?.split("-")[0] || defaultLocale;
|
|
6
|
+
return supportedLanguages.includes(locale2) ? locale2 : defaultLocale;
|
|
7
|
+
} else if (import.meta.client) {
|
|
8
|
+
const locale2 = navigator.language || defaultLocale;
|
|
9
|
+
return supportedLanguages.includes(locale2) ? locale2 : defaultLocale;
|
|
10
|
+
}
|
|
11
|
+
return defaultLocale;
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
locale
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LocaleKey } from "../types/generated-locales.js";
|
|
2
|
+
export type TranslationMap = readonly string[];
|
|
3
|
+
export type Locale<T extends TranslationMap> = T[number];
|
|
4
|
+
export type LocaleKeys<T extends TranslationMap> = T[keyof T];
|
|
5
|
+
export type TMultilinguistResponse<T extends TranslationMap> = {
|
|
6
|
+
t: (key: LocaleKey) => string;
|
|
7
|
+
setLocale: (locale: Locale<T>) => void;
|
|
8
|
+
initLocalization: () => Promise<void>;
|
|
9
|
+
locale: Ref<Locale<T>>;
|
|
10
|
+
};
|
|
11
|
+
export default function useLocalization<const T extends TranslationMap>(supportedLanguages: T, defaultLocale: Locale<T>): TMultilinguistResponse<T>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import useLocale from "../composables/useLocale.js";
|
|
2
|
+
export default function useLocalization(supportedLanguages, defaultLocale) {
|
|
3
|
+
const userSelectedLocale = useCookie("multilinguist-locale", { default: () => defaultLocale });
|
|
4
|
+
const { locale: userBrowserLocale } = useLocale(supportedLanguages, defaultLocale);
|
|
5
|
+
const loadedLanguages = useState("loaded-languages", () => ({}));
|
|
6
|
+
const loadDefaultLocale = async () => {
|
|
7
|
+
if (!loadedLanguages.value[defaultLocale]) {
|
|
8
|
+
const messages = await import(`@/public/locales/${defaultLocale}.json`);
|
|
9
|
+
loadedLanguages.value[defaultLocale] = messages.default;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
const userPrefferableLocale = computed(() => {
|
|
13
|
+
return userSelectedLocale.value ? userSelectedLocale.value : userBrowserLocale.value;
|
|
14
|
+
});
|
|
15
|
+
const locale = useState(() => {
|
|
16
|
+
return userPrefferableLocale.value || defaultLocale;
|
|
17
|
+
});
|
|
18
|
+
const t = (key) => {
|
|
19
|
+
const localeKeys = loadedLanguages.value[locale.value];
|
|
20
|
+
return String(localeKeys?.[key] || key);
|
|
21
|
+
};
|
|
22
|
+
const setLocale = async (newLocale) => {
|
|
23
|
+
if (!loadedLanguages.value[newLocale] && supportedLanguages.includes(newLocale)) {
|
|
24
|
+
const loadedLocale = await import(`@/public/locales/${newLocale}.json`).then(
|
|
25
|
+
(module) => module.default || module
|
|
26
|
+
);
|
|
27
|
+
loadedLanguages.value[newLocale] = loadedLocale;
|
|
28
|
+
}
|
|
29
|
+
userSelectedLocale.value = newLocale;
|
|
30
|
+
locale.value = newLocale;
|
|
31
|
+
};
|
|
32
|
+
const initLocalization = async () => {
|
|
33
|
+
await loadDefaultLocale();
|
|
34
|
+
await setLocale(userPrefferableLocale.value);
|
|
35
|
+
};
|
|
36
|
+
watch(
|
|
37
|
+
() => locale.value,
|
|
38
|
+
async (val) => {
|
|
39
|
+
if (val !== userSelectedLocale.value) {
|
|
40
|
+
userSelectedLocale.value = val;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
return {
|
|
45
|
+
t,
|
|
46
|
+
setLocale,
|
|
47
|
+
initLocalization,
|
|
48
|
+
locale
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default function useMultilinguist() {
|
|
2
|
+
const nuxtApp = useNuxtApp();
|
|
3
|
+
const localization = nuxtApp.$localization || nuxtApp._localization;
|
|
4
|
+
if (!localization) {
|
|
5
|
+
throw new Error("Localization plugin not initialized");
|
|
6
|
+
}
|
|
7
|
+
return { ...localization };
|
|
8
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import useLocalization from "../runtime/composables/useLocalization";
|
|
2
|
+
export default defineNuxtPlugin(async (nuxtApp) => {
|
|
3
|
+
const config = useRuntimeConfig().public.multilinguist || {
|
|
4
|
+
defaultLocale: "en",
|
|
5
|
+
supportedLanguages: ["en"]
|
|
6
|
+
};
|
|
7
|
+
const supportedLanguages = config.supportedLanguages;
|
|
8
|
+
const defaultLocale = config.defaultLocale;
|
|
9
|
+
const localization = useLocalization(supportedLanguages, defaultLocale);
|
|
10
|
+
await localization.initLocalization();
|
|
11
|
+
console.log("[multilinguist] is initialised", config.supportedLanguages, config.defaultLocale);
|
|
12
|
+
nuxtApp.provide("localization", localization);
|
|
13
|
+
nuxtApp.provide("t", localization.t);
|
|
14
|
+
nuxtApp._localization = localization;
|
|
15
|
+
});
|
package/dist/types.d.mts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yiiamee/multilinguist",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Nuxt 3 Multilinguist Localization module",
|
|
5
|
+
"repository": "yiiameeMich/multilinguist",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/types.d.mts",
|
|
11
|
+
"import": "./dist/module.mjs"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/module.mjs",
|
|
15
|
+
"typesVersions": {
|
|
16
|
+
"*": {
|
|
17
|
+
".": [
|
|
18
|
+
"./dist/types.d.mts"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"prepack": "nuxt-module-build build",
|
|
27
|
+
"dev": "nuxi dev playground",
|
|
28
|
+
"dev:build": "nuxi build playground",
|
|
29
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
30
|
+
"release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
31
|
+
"lint": "eslint .",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:watch": "vitest watch",
|
|
34
|
+
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@nuxt/kit": "^3.17.4"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@nuxt/devtools": "^2.4.1",
|
|
41
|
+
"@nuxt/eslint-config": "^1.4.1",
|
|
42
|
+
"@nuxt/module-builder": "^1.0.1",
|
|
43
|
+
"@nuxt/schema": "^3.17.4",
|
|
44
|
+
"@nuxt/test-utils": "^3.19.1",
|
|
45
|
+
"@types/node": "latest",
|
|
46
|
+
"changelogen": "^0.6.1",
|
|
47
|
+
"eslint": "^9.27.0",
|
|
48
|
+
"nuxt": "^3.17.4",
|
|
49
|
+
"typescript": "~5.8.3",
|
|
50
|
+
"vitest": "^3.1.4",
|
|
51
|
+
"vue-tsc": "^2.2.10"
|
|
52
|
+
}
|
|
53
|
+
}
|