astro-i18nya 0.1.0 → 0.1.1

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,15 +1,53 @@
1
1
  # astro-i18nya
2
2
 
3
- To install dependencies:
3
+ I18n support for astro.
4
4
 
5
- ```bash
6
- bun install
5
+ ## Features
6
+
7
+ - Integration with `i18nya` and `astro`
8
+ - A `<Trans />` component that works better than the one in `react-i18next`!
9
+
10
+ ## Installation
11
+
12
+ ```sh
13
+ npx astro add astro-i18nya
14
+ # or
15
+ npm install astro-i18nya
7
16
  ```
8
17
 
9
- To run:
18
+ Make sure you called `init()` from `i18nya` in `src/i18n.ts`:
19
+
20
+ ```ts
21
+ import { init } from 'i18nya';
10
22
 
11
- ```bash
12
- bun run index.ts
23
+ const i18nya = await init({ ... });
24
+ export default i18nya;
13
25
  ```
14
26
 
15
- This project was created using `bun init` in bun v1.3.2. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
27
+ Then in `astro.config.mjs`:
28
+
29
+ ```ts
30
+ import i18nya from "./i18n";
31
+ import astro_i18nya from "astro-i18nya";
32
+
33
+ export default defineConfig({
34
+ integrations: [astro_i18nya(i18nya)],
35
+ // `i18n:` is not needed
36
+ });
37
+ ```
38
+
39
+ ## Trans
40
+
41
+ ```tsx
42
+ <Trans t={t("test", { user: "John" })}>
43
+ <b />
44
+ <a href="https://example.com" />
45
+ </Trans>
46
+ ```
47
+
48
+ With `"test": "Hello <1>{{user}}</1>, welcome to <2><1>my site</1></2>."`, the above element will become:
49
+
50
+ ```html
51
+ <b>Hello John</b>, welcome to <a href="https://example.com"><b>my site</b></a
52
+ >.
53
+ ```
@@ -0,0 +1,31 @@
1
+ import type { ReactNode } from "react";
2
+ type Props = {
3
+ children: ReactNode;
4
+ t: string;
5
+ };
6
+ /**
7
+ * A fake version of `<Trans>` in `react-i18next` with *very different* behaviour.
8
+ *
9
+ * You feed in a list of empty elements in `<Trans>`. The structure will follow the translation strings.
10
+ *
11
+ * IMPORTANT: It is **HIGHLY RECOMMENDED** to use `experimentalReactChildren: true` for `@astrojs/react` in your astro config,
12
+ * otherwise this will not work correctly outside of `.tsx` files.
13
+ *
14
+ * @example ```tsx
15
+ * <Trans t={t("test", { user: "John" })}>
16
+ * <b />
17
+ * <a href="https://example.com" />
18
+ * </Trans>
19
+ * ```
20
+ * With `"test": "Hello <1>{{user}}</1>, welcome to <2><1>my site</1></2>."`, the above element will become:
21
+ * ```tsx
22
+ * <b>Hello John</b>, welcome to <a href="https://example.com"><b>my site</b></a>.
23
+ * ```
24
+ *
25
+ * @param children the list of tags.
26
+ * @param t return value of t()
27
+ * @returns ReactNode
28
+ */
29
+ declare const _default: ({ children, t }: Props) => string | import("react/jsx-runtime").JSX.Element;
30
+ export default _default;
31
+ //# sourceMappingURL=Trans.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Trans.d.ts","sourceRoot":"","sources":["../src/Trans.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAqB,SAAS,EAAE,MAAM,OAAO,CAAC;AAE1D,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,SAAS,CAAC;IACpB,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;0CAC+B,KAAK;AAAvC,wBAsDsC"}
package/dist/Trans.js ADDED
@@ -0,0 +1,81 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ //? https://react.i18next.com/latest/trans-component
3
+ // do something similar to ↑
4
+ import { Children, cloneElement, isValidElement } from "react";
5
+ /**
6
+ * A fake version of `<Trans>` in `react-i18next` with *very different* behaviour.
7
+ *
8
+ * You feed in a list of empty elements in `<Trans>`. The structure will follow the translation strings.
9
+ *
10
+ * IMPORTANT: It is **HIGHLY RECOMMENDED** to use `experimentalReactChildren: true` for `@astrojs/react` in your astro config,
11
+ * otherwise this will not work correctly outside of `.tsx` files.
12
+ *
13
+ * @example ```tsx
14
+ * <Trans t={t("test", { user: "John" })}>
15
+ * <b />
16
+ * <a href="https://example.com" />
17
+ * </Trans>
18
+ * ```
19
+ * With `"test": "Hello <1>{{user}}</1>, welcome to <2><1>my site</1></2>."`, the above element will become:
20
+ * ```tsx
21
+ * <b>Hello John</b>, welcome to <a href="https://example.com"><b>my site</b></a>.
22
+ * ```
23
+ *
24
+ * @param children the list of tags.
25
+ * @param t return value of t()
26
+ * @returns ReactNode
27
+ */
28
+ export default (({ children, t }) => {
29
+ // find /<\/(\d+)>/g, where group 1 parse to int is largest
30
+ const maxTagId = Math.max(...t.match(/<\/(\d+)>/g).map((i) => parseInt(i.slice(2, -1))));
31
+ const inputs = Children.toArray(children).filter((c) => isValidElement(c));
32
+ if ((maxTagId ?? 0) > inputs.length) {
33
+ return t; // syntax error
34
+ }
35
+ const elms = []; // resulting list of elements
36
+ const tagStack = [];
37
+ for (let ch_idx = 0; ch_idx < t.length;) {
38
+ if (t.substring(ch_idx, ch_idx + 2) == "\\<") {
39
+ elms.push("<");
40
+ ch_idx += 2;
41
+ continue;
42
+ }
43
+ if (t.substring(ch_idx, ch_idx + 2) == "</") {
44
+ let j = 0;
45
+ while (t[++j + ch_idx] != ">" && j + ch_idx < t.length)
46
+ ;
47
+ const tag = Number.parseInt(t.substring(++ch_idx + 1, (ch_idx += j)));
48
+ if (Number.isNaN(tag)) {
49
+ elms.push(t.substring(ch_idx - j - 1, ch_idx));
50
+ continue;
51
+ }
52
+ let { p, l } = tagStack.pop();
53
+ if (tag != p) {
54
+ return t; // syntax error
55
+ }
56
+ elms.push(cloneElement(inputs[p - 1], {}, ...elms.splice(l, elms.length - l)));
57
+ continue;
58
+ }
59
+ if (t[ch_idx] == "<") {
60
+ let j = 0;
61
+ while (t[++j + ch_idx] != ">" && j + ch_idx < t.length)
62
+ ;
63
+ const tag = Number.parseInt(t.substring(++ch_idx, (ch_idx += j)));
64
+ if (Number.isNaN(tag)) {
65
+ elms.push(t.substring(ch_idx - j - 1, ch_idx));
66
+ continue;
67
+ }
68
+ tagStack.push({ p: tag, l: elms.length });
69
+ elms.push(""); // in order to splice later, contents inside a new tag element must start fresh
70
+ continue;
71
+ }
72
+ if (typeof elms[elms.length - 1] === "string") {
73
+ elms[elms.length - 1] += t[ch_idx++];
74
+ }
75
+ else {
76
+ elms.push(t[ch_idx++]);
77
+ }
78
+ }
79
+ return _jsx(_Fragment, { children: elms });
80
+ });
81
+ //# sourceMappingURL=Trans.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Trans.js","sourceRoot":"","sources":["../src/Trans.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { I18Nya } from "i18nya";
2
+ import type { AstroIntegration } from "astro";
3
+ import Trans from "./Trans.js";
4
+ import { listLang, getLangName, makeGetStaticPaths } from "./util.js";
5
+ export { Trans, listLang, getLangName, makeGetStaticPaths };
6
+ export default function astroI18nya<T extends string | number | symbol>(i18nya: I18Nya<T>): AstroIntegration;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;AAE5D,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,EACpE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAChB,gBAAgB,CAqBlB"}
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ import Trans from "./Trans.js";
2
+ import { listLang, getLangName, makeGetStaticPaths } from "./util.js";
3
+ export { Trans, listLang, getLangName, makeGetStaticPaths };
4
+ export default function astroI18nya(i18nya) {
5
+ return {
6
+ name: "astro-i18nya",
7
+ hooks: {
8
+ "astro:config:setup": ({ updateConfig }) => {
9
+ updateConfig({
10
+ i18n: {
11
+ defaultLocale: i18nya.config.defaultLang,
12
+ locales: Object.keys(i18nya.translations),
13
+ routing: {
14
+ prefixDefaultLocale: false,
15
+ redirectToDefaultLocale: true,
16
+ fallbackType: "redirect",
17
+ },
18
+ },
19
+ // required for <Trans>
20
+ // integrations: [react({ experimentalReactChildren: true })],
21
+ });
22
+ },
23
+ },
24
+ };
25
+ }
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;AAE5D,MAAM,CAAC,OAAO,UAAU,WAAW,CACjC,MAAiB;IAEjB,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,KAAK,EAAE;YACL,oBAAoB,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE;gBACzC,YAAY,CAAC;oBACX,IAAI,EAAE;wBACJ,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;wBACxC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;wBACzC,OAAO,EAAE;4BACP,mBAAmB,EAAE,KAAK;4BAC1B,uBAAuB,EAAE,IAAI;4BAC7B,YAAY,EAAE,UAAU;yBACzB;qBACF;oBACD,uBAAuB;oBACvB,8DAA8D;iBAC/D,CAAC,CAAC;YACL,CAAC;SACF;KACF,CAAC;AACJ,CAAC"}
package/dist/util.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import type { I18Nya } from "i18nya";
2
+ /**
3
+ * Obtain the language name.
4
+ * @param lang the language locale
5
+ * @param displayLang in what language should the name of the language be shown. By default, use native language names.
6
+ * @returns language name
7
+ */
8
+ export declare const getLangName: (lang: string, displayLang?: string) => string;
9
+ /**
10
+ * List out available languages.
11
+ * @param i18nya return value of `init()` from `i18nya`
12
+ * @param displayLang in what language should the name of the language be shown. By default, use native language names.
13
+ * @returns a map of language locale → language name
14
+ */
15
+ export declare const listLang: <T extends string | number | symbol>(i18nya: I18Nya<T>, displayLang?: string) => Map<string, string>;
16
+ export declare const makeGetStaticPaths: <T extends string | number | symbol>(i18nya: I18Nya<T>) => () => Promise<{
17
+ params: {
18
+ lang: string;
19
+ };
20
+ }[]>;
21
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,EAAE,cAAc,MAAM,WACe,CAAC;AAE9E;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,EACzD,QAAQ,MAAM,CAAC,CAAC,CAAC,EACjB,cAAc,MAAM,wBAOnB,CAAC;AAEJ,eAAO,MAAM,kBAAkB,GAC5B,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,QAAQ,MAAM,CAAC,CAAC,CAAC;;;;IAIN,CAAC"}
package/dist/util.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Obtain the language name.
3
+ * @param lang the language locale
4
+ * @param displayLang in what language should the name of the language be shown. By default, use native language names.
5
+ * @returns language name
6
+ */
7
+ export const getLangName = (lang, displayLang) => new Intl.DisplayNames([displayLang ?? lang], { type: "language" }).of(lang);
8
+ /**
9
+ * List out available languages.
10
+ * @param i18nya return value of `init()` from `i18nya`
11
+ * @param displayLang in what language should the name of the language be shown. By default, use native language names.
12
+ * @returns a map of language locale → language name
13
+ */
14
+ export const listLang = (i18nya, displayLang) => new Map(Object.keys(i18nya.translations).map((l) => [
15
+ l,
16
+ getLangName(l.replace("_", "-"), displayLang),
17
+ ]));
18
+ export const makeGetStaticPaths = (i18nya) => async () => Object.keys(i18nya.translations)
19
+ .filter((lang) => lang !== i18nya.config.defaultLang)
20
+ .map((lang) => ({ params: { lang: lang } }));
21
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,WAAoB,EAAE,EAAE,CAChE,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,MAAiB,EACjB,WAAoB,EACpB,EAAE,CACF,IAAI,GAAG,CACL,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC1C,CAAC;IACD,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,WAAW,CAAC;CAC9C,CAAC,CACH,CAAC;AAEJ,MAAM,CAAC,MAAM,kBAAkB,GAC7B,CAAqC,MAAiB,EAAE,EAAE,CAC1D,KAAK,IAAI,EAAE,CACT,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;KAC7B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;KACpD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "astro-i18nya",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Astro integration for i18nya: i18n as small as a cat's paw",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
+ "type": "module",
7
8
  "scripts": {
8
9
  "build": "tsc",
9
10
  "test": "jest"
@@ -12,8 +13,12 @@
12
13
  "type": "git",
13
14
  "url": "git+https://github.com/FyraLabs/i18nya.git"
14
15
  },
16
+ "jest": {
17
+ "testPathIgnorePatterns": ["<rootDir>/dist"]
18
+ },
15
19
  "keywords": [
16
20
  "astro",
21
+ "astro-integration",
17
22
  "internationalization",
18
23
  "i18n",
19
24
  "translation",
@@ -38,6 +43,7 @@
38
43
  "@types/node": "^24.10.1",
39
44
  "babel-jest": "^30.2.0",
40
45
  "jest": "^30.2.0",
46
+ "jest-environment-jsdom": "^30.2.0",
41
47
  "react-test-renderer": "^19.2.0",
42
48
  "typescript": "^5.9.3"
43
49
  },
@@ -45,10 +51,8 @@
45
51
  "typescript": "^5"
46
52
  },
47
53
  "dependencies": {
48
- "@astrojs/react": "^4.4.2",
49
54
  "astro": "^5.16.0",
50
55
  "i18nya": "^0.1.0",
51
- "jest-environment-jsdom": "^30.2.0",
52
56
  "react": "^19.2.0"
53
57
  }
54
58
  }
package/src/Trans.tsx CHANGED
@@ -13,6 +13,9 @@ type Props = {
13
13
  * A fake version of `<Trans>` in `react-i18next` with *very different* behaviour.
14
14
  *
15
15
  * You feed in a list of empty elements in `<Trans>`. The structure will follow the translation strings.
16
+ *
17
+ * IMPORTANT: It is **HIGHLY RECOMMENDED** to use `experimentalReactChildren: true` for `@astrojs/react` in your astro config,
18
+ * otherwise this will not work correctly outside of `.tsx` files.
16
19
  *
17
20
  * @example ```tsx
18
21
  * <Trans t={t("test", { user: "John" })}>
package/src/index.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import type { I18Nya } from "i18nya";
2
2
  import type { AstroIntegration } from "astro";
3
- import react from "@astrojs/react";
4
- import Trans from "./Trans";
5
- import { listLang, getLangName } from "./util";
6
- export { Trans, listLang, getLangName };
3
+ import Trans from "./Trans.js";
4
+ import { listLang, getLangName, makeGetStaticPaths } from "./util.js";
5
+ export { Trans, listLang, getLangName, makeGetStaticPaths };
7
6
 
8
- export default function (i18nya: I18Nya): AstroIntegration {
7
+ export default function astroI18nya<T extends string | number | symbol>(
8
+ i18nya: I18Nya<T>,
9
+ ): AstroIntegration {
9
10
  return {
10
11
  name: "astro-i18nya",
11
12
  hooks: {
@@ -14,9 +15,14 @@ export default function (i18nya: I18Nya): AstroIntegration {
14
15
  i18n: {
15
16
  defaultLocale: i18nya.config.defaultLang,
16
17
  locales: Object.keys(i18nya.translations),
18
+ routing: {
19
+ prefixDefaultLocale: false,
20
+ redirectToDefaultLocale: true,
21
+ fallbackType: "redirect",
22
+ },
17
23
  },
18
24
  // required for <Trans>
19
- integrations: [react({ experimentalReactChildren: true })],
25
+ // integrations: [react({ experimentalReactChildren: true })],
20
26
  });
21
27
  },
22
28
  },
package/src/util.ts CHANGED
@@ -15,10 +15,20 @@ export const getLangName = (lang: string, displayLang?: string) =>
15
15
  * @param displayLang in what language should the name of the language be shown. By default, use native language names.
16
16
  * @returns a map of language locale → language name
17
17
  */
18
- export const listLang = (i18nya: I18Nya, displayLang?: string) =>
18
+ export const listLang = <T extends string | number | symbol>(
19
+ i18nya: I18Nya<T>,
20
+ displayLang?: string,
21
+ ) =>
19
22
  new Map(
20
23
  Object.keys(i18nya.translations).map((l) => [
21
24
  l,
22
25
  getLangName(l.replace("_", "-"), displayLang),
23
26
  ]),
24
27
  );
28
+
29
+ export const makeGetStaticPaths =
30
+ <T extends string | number | symbol>(i18nya: I18Nya<T>) =>
31
+ async () =>
32
+ Object.keys(i18nya.translations)
33
+ .filter((lang) => lang !== i18nya.config.defaultLang)
34
+ .map((lang) => ({ params: { lang: lang } }));
package/tsconfig.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
- "exclude": ["./dist"],
2
+ "extends": "astro/tsconfigs/base",
3
+ "exclude": ["./dist", "*.config.*", "**/*.test.*"],
3
4
  "compilerOptions": {
4
5
  "rootDir": "./src",
5
6
  "outDir": "./dist",
6
7
 
7
8
  // Environment setup & latest features
8
- "lib": ["ESNext"],
9
+ "lib": ["ESNext", "DOM"],
9
10
  "target": "ESNext",
10
11
  "module": "Preserve",
11
12
  "moduleDetection": "force",
@@ -19,9 +20,10 @@
19
20
  "declarationMap": true,
20
21
 
21
22
  // Module resolution
22
- "moduleResolution": "bundler",
23
- "allowImportingTsExtensions": true,
24
- "noEmit": true,
23
+ // "moduleResolution": "node16",
24
+ // "allowImportingTsExtensions": true,
25
+ "noEmit": false,
26
+ "allowImportingTsExtensions": false,
25
27
  "verbatimModuleSyntax": false,
26
28
  "isolatedModules": true,
27
29
  "resolveJsonModule": true,